<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.10">
<title>Spring Cloud Config</title>
<style>
@import url(//cdnjs.cloudflare.com/ajax/libs/font-awesome/3.2.0/css/font-awesome.css);
/* normalize.css v2.1.1 | MIT License | git.io/normalize */
/* ========================================================================== HTML5 display definitions ========================================================================== */
/** Correct `block` display not defined in IE 8/9. */
article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }

/** Correct `inline-block` display not defined in IE 8/9. */
audio, canvas, video { display: inline-block; }

/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
audio:not([controls]) { display: none; height: 0; }

/** Address styling not present in IE 8/9. */
[hidden] { display: none; }

/* ========================================================================== Base ========================================================================== */
/** 1. Prevent system color scheme's background color being used in Firefox, IE, and Opera. 2. Prevent system color scheme's text color being used in Firefox, IE, and Opera. 3. Set default font family to sans-serif. 4. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
html { background: #fff; /* 1 */ color: #000; /* 2 */ font-family: sans-serif; /* 3 */ -ms-text-size-adjust: 100%; /* 4 */ -webkit-text-size-adjust: 100%; /* 4 */ }

/** Remove default margin. */
body { margin: 0; }

/* ========================================================================== Links ========================================================================== */
/** Address `outline` inconsistency between Chrome and other browsers. */
a:focus { outline: thin dotted; }

/** Improve readability when focused and also mouse hovered in all browsers. */
a:active, a:hover { outline: 0; }

/* ========================================================================== Typography ========================================================================== */
/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
h1 { font-size: 2em; margin: 0.67em 0; }

/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
abbr[title] { border-bottom: 1px dotted; }

/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
b, strong { font-weight: bold; }

/** Address styling not present in Safari 5 and Chrome. */
dfn { font-style: italic; }

/** Address differences between Firefox and other browsers. */
hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }

/** Address styling not present in IE 8/9. */
mark { background: #ff0; color: #000; }

/** Correct font family set oddly in Safari 5 and Chrome. */
code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }

/** Improve readability of pre-formatted text in all browsers. */
pre { white-space: pre-wrap; }

/** Set consistent quote types. */
q { quotes: "\201C" "\201D" "\2018" "\2019"; }

/** Address inconsistent and variable font size in all browsers. */
small { font-size: 80%; }

/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }

sup { top: -0.5em; }

sub { bottom: -0.25em; }

/* ========================================================================== Embedded content ========================================================================== */
/** Remove border when inside `a` element in IE 8/9. */
img { border: 0; }

/** Correct overflow displayed oddly in IE 9. */
svg:not(:root) { overflow: hidden; }

/* ========================================================================== Figures ========================================================================== */
/** Address margin not present in IE 8/9 and Safari 5. */
figure { margin: 0; }

/* ========================================================================== Forms ========================================================================== */
/** Define consistent border, margin, and padding. */
fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }

/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
legend { border: 0; /* 1 */ padding: 0; /* 2 */ }

/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }

/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
button, input { line-height: normal; }

/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
button, select { text-transform: none; }

/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }

/** Re-set default cursor for disabled elements. */
button[disabled], html input[disabled] { cursor: default; }

/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }

/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }

/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }

/** Remove inner padding and border in Firefox 4+. */
button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }

/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }

/* ========================================================================== Tables ========================================================================== */
/** Remove most spacing between table cells. */
table { border-collapse: collapse; border-spacing: 0; }

*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }

html, body { font-size: 15px; }

body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }

a:hover { cursor: pointer; }

a:focus { outline: none; }

img, object, embed { max-width: 100%; height: auto; }

object, embed { height: 100%; }

img { -ms-interpolation-mode: bicubic; }

#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }

.left { float: left !important; }

.right { float: right !important; }

.text-left { text-align: left !important; }

.text-right { text-align: right !important; }

.text-center { text-align: center !important; }

.text-justify { text-align: justify !important; }

.hide { display: none; }

.antialiased, body { -webkit-font-smoothing: antialiased; }

img { display: inline-block; vertical-align: middle; }

textarea { height: auto; min-height: 50px; }

select { width: 100%; }

p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.23333em; line-height: 1.6; }

.subheader, #content #toctitle, .admonitionblock td.content > .title, .exampleblock > .title, .imageblock > .title, .videoblock > .title, .listingblock > .title, .literalblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, .sidebarblock > .title, .tableblock > .title, .verseblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title, .tableblock > caption { line-height: 1.4; color: #777777; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }

/* Typography resets */
div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }

/* Default Link Styles */
a { color: #4183c4; text-decoration: none; line-height: inherit; }
a:hover, a:focus { color: #4183c4; }
a img { border: none; }

/* Default paragraph styles */
p { font-family: helvetica, arial, freesans, clean, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 1em; text-rendering: optimizeLegibility; }
p aside { font-size: 0.93333em; line-height: 1.35; font-style: italic; }

/* Default header styles */
h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: helvetica, arial, freesans, clean, sans-serif; font-weight: bold; font-style: normal; color: #333333; text-rendering: optimizeLegibility; margin-top: 0.2em; margin-bottom: 0.5em; line-height: 1.2em; }
h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: gray; line-height: 0; }

h1 { font-size: 1.33333em; }

h2 { font-size: 0.93333em; }

h3, #toctitle, .sidebarblock > .content > .title { font-size: 0.86667em; }

h4 { font-size: 0.66667em; }

h5 { font-size: 1em; }

h6 { font-size: 1em; }

hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.33333em 0 1.26667em; height: 0; }

/* Helpful Typography Defaults */
em, i { font-style: italic; line-height: inherit; }

strong, b { font-weight: bold; line-height: inherit; }

small { font-size: 60%; line-height: inherit; }

code { font-family: Monaco, "DejaVu Sans Mono", "Courier New", monospace; font-weight: normal; color: #666666; }

/* Lists */
ul, ol, dl { font-size: 1em; line-height: 1.4; margin-bottom: 1em; list-style-position: outside; font-family: helvetica, arial, freesans, clean, sans-serif; }

ul, ol { margin-left: 0.7em; }

/* Unordered Lists */
ul li ul, ul li ol { margin-left: 1.33333em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
ul.square { list-style-type: square; }
ul.circle { list-style-type: circle; }
ul.disc { list-style-type: disc; }
ul.no-bullet { list-style: none; }

/* Ordered Lists */
ol li ul, ol li ol { margin-left: 1.33333em; margin-bottom: 0; }

/* Definition Lists */
dl dt { margin-bottom: 0.33333em; font-weight: bold; }
dl dd { margin-bottom: 1.33333em; }

/* Abbreviations */
abbr, acronym { text-transform: uppercase; font-size: 90%; color: #333333; border-bottom: 1px dotted #dddddd; cursor: help; }

abbr { text-transform: none; }

/* Blockquotes */
blockquote { margin: 0 0 1em; padding: 0; border-left: none; }
blockquote cite { display: block; font-size: 0.86667em; color: #666666; }
blockquote cite:before { content: "\2014 \0020"; }
blockquote cite a, blockquote cite a:visited { color: #666666; }

blockquote, blockquote p { line-height: 1.4; color: #666666; }

/* Microformats */
.vcard { display: inline-block; margin: 0 0 1.33333em 0; border: 1px solid #dddddd; padding: 0.66667em 0.8em; }
.vcard li { margin: 0; display: block; }
.vcard .fn { font-weight: bold; font-size: 1em; }

.vevent .summary { font-weight: bold; }
.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.06667em; }

@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
  h1 { font-size: 2em; }
  h2 { font-size: 1.6em; }
  h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.2em; }
  h4 { font-size: 1em; } }
/* Print styles.  Inlined to avoid required HTTP connection: www.phpied.com/delay-loading-your-print-css/ Credit to Paul Irish and HTML5 Boilerplate (html5boilerplate.com)
*/
.print-only { display: none !important; }

@media print { * { background: transparent !important; color: #000 !important; /* Black prints faster: h5bp.com/s */ box-shadow: none !important; text-shadow: none !important; }
  a, a:visited { text-decoration: underline; }
  a[href]:after { content: " (" attr(href) ")"; }
  abbr[title]:after { content: " (" attr(title) ")"; }
  .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
  thead { display: table-header-group; /* h5bp.com/t */ }
  tr, img { page-break-inside: avoid; }
  img { max-width: 100% !important; }
  @page { margin: 0.5cm; }
  p, h2, h3, #toctitle, .sidebarblock > .content > .title { orphans: 3; widows: 3; }
  h2, h3, #toctitle, .sidebarblock > .content > .title { page-break-after: avoid; }
  .hide-on-print { display: none !important; }
  .print-only { display: block !important; }
  .hide-for-print { display: none !important; }
  .show-for-print { display: inherit !important; } }
/* Tables */
table { background: white; margin-bottom: 1.33333em; border: solid 1px #dddddd; }
table thead, table tfoot { background: whitesmoke; font-weight: bold; }
table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.53333em 0.66667em 0.66667em; font-size: 0.93333em; color: #222222; text-align: left; }
table tr th, table tr td { padding: 0.6em 0.66667em; font-size: 0.8em; color: #222222; }
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #f9f9f9; }
table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; }

a:hover, a:focus { text-decoration: underline; }

.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
.clearfix:after, .float-group:after { clear: both; }

*:not(pre) > code { font-size: 0.86667em; padding: 1px 5px 1px 5px; white-space: nowrap; background-color: transparent; border: 1px solid #dddddd; -webkit-border-radius: 3px; border-radius: 3px; text-shadow: none; }

pre, pre > code { line-height: 1.6; color: white; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; }

kbd.keyseq { color: #666666; }

kbd:not(.keyseq) { display: inline-block; color: #333333; font-size: 0.8em; line-height: 1.4; background-color: #F7F7F7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; margin: -0.15em 0.15em 0 0.15em; padding: 0.2em 0.6em 0.2em 0.5em; vertical-align: middle; white-space: nowrap; }

kbd kbd:first-child { margin-left: 0; }

kbd kbd:last-child { margin-right: 0; }

.menuseq, .menu { color: #1a1a1a; }

#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 66.66667em; *zoom: 1; position: relative; padding-left: 1em; padding-right: 1em; }
#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }

#header { margin-bottom: 2.66667em; }
#header > h1 { color: #333333; font-weight: 300; border-bottom: 1px solid #dddddd; margin-bottom: -28px; padding-bottom: 32px; }
#header span { color: #666666; }
#header #revnumber { text-transform: capitalize; }
#header br { display: none; }
#header br + span { padding-left: 3px; }
#header br + span:before { content: "\2013 \0020"; }
#header br + span.author { padding-left: 0; }
#header br + span.author:before { content: ", "; }

#toc { border-bottom: 0 solid #dddddd; padding-bottom: 1.33333em; }
#toc > ul { margin-left: 0.26667em; }
#toc ul.sectlevel0 > li > a { font-style: italic; }
#toc ul.sectlevel0 ul.sectlevel1 { margin-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
#toc ul { list-style-type: none; }

#toctitle { color: #777777; }

@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; }
  #toc.toc2 { position: fixed; width: 20em; left: 0; top: 0; border-right: 1px solid #dddddd; border-bottom: 0; z-index: 1000; padding: 1em; height: 100%; overflow: auto; }
  #toc.toc2 #toctitle { margin-top: 0; }
  #toc.toc2 > ul { font-size: .95em; }
  #toc.toc2 ul ul { margin-left: 0; padding-left: 1.33333em; }
  #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
  body.toc2.toc-right { padding-left: 0; padding-right: 20em; }
  body.toc2.toc-right #toc.toc2 { border-right: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } }
#content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.33333em; padding: 1.33333em; background: white; border-width: 0; -webkit-border-radius: 3px; border-radius: 3px; }
#content #toc > :first-child { margin-top: 0; }
#content #toc > :last-child { margin-bottom: 0; }
#content #toc a { text-decoration: none; }

#content #toctitle { font-weight: bold; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 1.06667em; padding-left: 0.13333em; }

#footer { max-width: 100%; background-color: whitesmoke; padding: 1.33333em; }

#footer-text { color: #333333; line-height: 1.26; }

.sect1 { padding-bottom: 1.33333em; }

.sect1 + .sect1 { border-top: 0 solid #dddddd; }

#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; width: 1em; margin-left: -1em; display: block; text-decoration: none; visibility: hidden; text-align: center; font-weight: normal; }
#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: '\00A7'; font-size: .85em; vertical-align: text-top; display: block; margin-top: 0.05em; }
#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: #333333; text-decoration: none; }
#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: #262626; }

.imageblock, .literalblock, .listingblock, .verseblock, .videoblock { margin-bottom: 1.33333em; }

.admonitionblock td.content > .title, .exampleblock > .title, .imageblock > .title, .videoblock > .title, .listingblock > .title, .literalblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, .sidebarblock > .title, .tableblock > .title, .verseblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-align: left; font-weight: bold; }

.tableblock > caption { text-align: left; font-weight: bold; white-space: nowrap; overflow: visible; max-width: 0; }

table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }

.admonitionblock > table { border: 0; background: none; width: 100%; }
.admonitionblock > table td.icon { text-align: center; width: 80px; }
.admonitionblock > table td.icon img { max-width: none; }
.admonitionblock > table td.icon .title { font-weight: bold; text-transform: uppercase; }
.admonitionblock > table td.content { padding-left: 1.2em; padding-right: 1.33333em; border-left: 1px solid #dddddd; color: #666666; }
.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }

.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.33333em; background: white; -webkit-border-radius: 3px; border-radius: 3px; }
.exampleblock > .content > :first-child { margin-top: 0; }
.exampleblock > .content > :last-child { margin-bottom: 0; }
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6, .exampleblock > .content p { color: #333333; }
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6 { line-height: 1; margin-bottom: 0.66667em; }
.exampleblock > .content h1.subheader, .exampleblock > .content h2.subheader, .exampleblock > .content h3.subheader, .exampleblock > .content .subheader#toctitle, .sidebarblock.exampleblock > .content > .subheader.title, .exampleblock > .content h4.subheader, .exampleblock > .content h5.subheader, .exampleblock > .content h6.subheader { line-height: 1.4; }

.exampleblock.result > .content { -webkit-box-shadow: 0 1px 8px #eaeaea; box-shadow: 0 1px 8px #eaeaea; }

.sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.33333em; padding: 1.33333em; background: white; -webkit-border-radius: 3px; border-radius: 3px; }
.sidebarblock > :first-child { margin-top: 0; }
.sidebarblock > :last-child { margin-bottom: 0; }
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6, .sidebarblock p { color: #333333; }
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6 { line-height: 1; margin-bottom: 0.66667em; }
.sidebarblock h1.subheader, .sidebarblock h2.subheader, .sidebarblock h3.subheader, .sidebarblock .subheader#toctitle, .sidebarblock > .content > .subheader.title, .sidebarblock h4.subheader, .sidebarblock h5.subheader, .sidebarblock h6.subheader { line-height: 1.4; }
.sidebarblock > .content > .title { color: #777777; margin-top: 0; line-height: 1.4; border-width: 0 0 1px 0; border-style: solid; border-color: #cacaca; }

.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }

.literalblock > .content pre, .listingblock > .content pre { background: #333333; border-width: 2px; border-style: solid; border-color: #dddddd; -webkit-border-radius: 3px; border-radius: 3px; padding: 0.66667em; word-wrap: break-word; }
.literalblock > .content pre.nowrap, .listingblock > .content pre.nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
.literalblock > .content pre > code, .listingblock > .content pre > code { display: block; }
@media only screen { .literalblock > .content pre, .listingblock > .content pre { font-size: 0.69333em; } }
@media only screen and (min-width: 768px) { .literalblock > .content pre, .listingblock > .content pre { font-size: 0.78em; } }
@media only screen and (min-width: 1280px) { .literalblock > .content pre, .listingblock > .content pre { font-size: 0.86667em; } }

.listingblock > .content { position: relative; }

.listingblock:hover code[class*=" language-"]:before { text-transform: uppercase; font-size: 0.9em; color: #999; position: absolute; top: 0.4em; right: 0.4em; }

.listingblock:hover code.asciidoc:before { content: "asciidoc"; }
.listingblock:hover code.clojure:before { content: "clojure"; }
.listingblock:hover code.css:before { content: "css"; }
.listingblock:hover code.groovy:before { content: "groovy"; }
.listingblock:hover code.html:before { content: "html"; }
.listingblock:hover code.java:before { content: "java"; }
.listingblock:hover code.javascript:before { content: "javascript"; }
.listingblock:hover code.python:before { content: "python"; }
.listingblock:hover code.ruby:before { content: "ruby"; }
.listingblock:hover code.scss:before { content: "scss"; }
.listingblock:hover code.xml:before { content: "xml"; }
.listingblock:hover code.yaml:before { content: "yaml"; }

.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }

.listingblock.terminal pre .command:not([data-prompt]):before { content: '$'; }

table.pyhltable { border: 0; margin-bottom: 0; }

table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; }

table.pyhltable td.code { padding-left: .75em; padding-right: 0; }

.highlight.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; }

.highlight.pygments .lineno { display: inline-block; margin-right: .25em; }

table.pyhltable .linenodiv { background-color: transparent !important; padding-right: 0 !important; }

.quoteblock { margin: 0 0 1em; padding: 0; border-left: none; }
.quoteblock blockquote { margin: 0 0 1em 0; padding: 0 0 0.6em 0; border: 0; }
.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
.quoteblock .attribution { margin-top: -.25em; padding-bottom: 0.6em; font-size: 0.86667em; color: #666666; }
.quoteblock .attribution br { display: none; }
.quoteblock .attribution cite { display: block; margin-bottom: 0.66667em; }

table thead th, table tfoot th { font-weight: bold; }

table.tableblock.grid-all { border-collapse: separate; border-spacing: 1px; -webkit-border-radius: 3px; border-radius: 3px; border-top: 1px solid #dddddd; border-bottom: 1px solid #dddddd; }

table.tableblock.frame-topbot, table.tableblock.frame-none { border-left: 0; border-right: 0; }

table.tableblock.frame-sides, table.tableblock.frame-none { border-top: 0; border-bottom: 0; }

table.tableblock td .paragraph:last-child p, table.tableblock td > p:last-child { margin-bottom: 0; }

th.tableblock.halign-left, td.tableblock.halign-left { text-align: left; }

th.tableblock.halign-right, td.tableblock.halign-right { text-align: right; }

th.tableblock.halign-center, td.tableblock.halign-center { text-align: center; }

th.tableblock.valign-top, td.tableblock.valign-top { vertical-align: top; }

th.tableblock.valign-bottom, td.tableblock.valign-bottom { vertical-align: bottom; }

th.tableblock.valign-middle, td.tableblock.valign-middle { vertical-align: middle; }

p.tableblock.header { color: #222222; font-weight: bold; }

td > div.verse { white-space: pre; }

ol { margin-left: 0.96667em; }

ul li ol { margin-left: 0.7em; }

dl dd { margin-left: 1.125em; }

dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }

ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.5em; }

ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; }

ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.66667em; }

ul.checklist li > p:first-child > i[class^="icon-check"]:first-child, ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }

ul.checklist li > p:first-child > input[type="checkbox"]:first-child { position: relative; top: 1px; }

ul.inline { margin: 0 auto 0.5em auto; margin-left: -1.46667em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; }
ul.inline > li { list-style: none; float: left; margin-left: 1.46667em; display: block; }
ul.inline > li > * { display: block; }

.unstyled dl dt { font-weight: normal; font-style: normal; }

ol.arabic { list-style-type: decimal; }

ol.decimal { list-style-type: decimal-leading-zero; }

ol.loweralpha { list-style-type: lower-alpha; }

ol.upperalpha { list-style-type: upper-alpha; }

ol.lowerroman { list-style-type: lower-roman; }

ol.upperroman { list-style-type: upper-roman; }

ol.lowergreek { list-style-type: lower-greek; }

.hdlist > table, .colist > table { border: 0; background: none; }
.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }

td.hdlist1 { padding-right: .8em; font-weight: bold; }

td.hdlist1, td.hdlist2 { vertical-align: top; }

.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }

.colist > table tr > td:first-of-type { padding: 0 .8em; line-height: 1; }
.colist > table tr > td:last-of-type { padding: 0.26667em 0; }

.qanda > ol > li > p > em:only-child { color: #3876b4; }

.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }

.imageblock.left, .imageblock[style*="float: left"] { margin: 0.26667em 0.66667em 1.33333em 0; }
.imageblock.right, .imageblock[style*="float: right"] { margin: 0.26667em 0 1.33333em 0.66667em; }
.imageblock > .title { margin-bottom: 0; }
.imageblock.thumb, .imageblock.th { border-width: 6px; }
.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.13333em; }

.image.left, .image.right { margin-top: 0.26667em; margin-bottom: 0.26667em; display: inline-block; line-height: 0; }
.image.left { margin-right: 0.66667em; }
.image.right { margin-left: 0.66667em; }

a.image { text-decoration: none; }

span.footnote, span.footnoteref { vertical-align: super; font-size: 0.93333em; }
span.footnote a, span.footnoteref a { text-decoration: none; }

#footnotes { padding-top: 0.8em; padding-bottom: 0.8em; margin-bottom: 0.66667em; }
#footnotes hr { width: 20%; min-width: 6.66667em; margin: -.25em 0 .75em 0; border-width: 1px 0 0 0; }
#footnotes .footnote { padding: 0 0.4em; line-height: 1.3; font-size: 0.93333em; margin-left: 1.2em; text-indent: -1.2em; margin-bottom: .2em; }
#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; }
#footnotes .footnote:last-of-type { margin-bottom: 0; }

#content #footnotes { margin-top: -0.66667em; margin-bottom: 0; padding: 0.8em 0; }

.gist .file-data > table { border: none; background: #fff; width: 100%; margin-bottom: 0; }
.gist .file-data > table td.line-data { width: 99%; }

div.unbreakable { page-break-inside: avoid; }

.big { font-size: larger; }

.small { font-size: smaller; }

.underline { text-decoration: underline; }

.overline { text-decoration: overline; }

.line-through { text-decoration: line-through; }

.aqua { color: #00bfbf; }

.aqua-background { background-color: #00fafa; }

.black { color: black; }

.black-background { background-color: black; }

.blue { color: #0000bf; }

.blue-background { background-color: #0000fa; }

.fuchsia { color: #bf00bf; }

.fuchsia-background { background-color: #fa00fa; }

.gray { color: #606060; }

.gray-background { background-color: #7d7d7d; }

.green { color: #006000; }

.green-background { background-color: #007d00; }

.lime { color: #00bf00; }

.lime-background { background-color: #00fa00; }

.maroon { color: #600000; }

.maroon-background { background-color: #7d0000; }

.navy { color: #000060; }

.navy-background { background-color: #00007d; }

.olive { color: #606000; }

.olive-background { background-color: #7d7d00; }

.purple { color: #600060; }

.purple-background { background-color: #7d007d; }

.red { color: #bf0000; }

.red-background { background-color: #fa0000; }

.silver { color: #909090; }

.silver-background { background-color: #bcbcbc; }

.teal { color: #006060; }

.teal-background { background-color: #007d7d; }

.white { color: #bfbfbf; }

.white-background { background-color: #fafafa; }

.yellow { color: #bfbf00; }

.yellow-background { background-color: #fafa00; }

span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

.admonitionblock td.icon [class^="icon-"]:before { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #4183c4; color: #2e6295; }
.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }

.conum { display: inline-block; color: white !important; background-color: #333333; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; width: 20px; height: 20px; font-size: 12px; font-weight: bold; line-height: 20px; font-family: Arial, sans-serif; font-style: normal; position: relative; top: -2px; letter-spacing: -1px; }
.conum * { color: white !important; }
.conum + b { display: none; }
.conum:after { content: attr(data-value); }
.conum:not([data-value]):empty { display: none; }

p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1em; color: #666666; }

h2 { color: #325D72; border-bottom: 1px solid #dddddd; }

#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { color: #333333; }

#header, #content, #footnotes { padding-left: 0; padding-right: 0; }

#content ul { list-style-type: none; }
#content ul li { background: url('./images/li-chevron.png?1372292342') 0 0.4em no-repeat; padding-left: .7em; }

.olist.procedure > ol { counter-reset: li; list-style: none; position: relative; }
.olist.procedure > ol > li { position: relative; padding: 5px 0 5px 55px; margin-bottom: 5px; }
.olist.procedure > ol > li:before { content: counter(li); counter-increment: li; position: absolute; top: 0; left: 0; height: 100%; width: 30px; padding: 0 10px 0 0; color: #999; font-size: 1.46667em; font-weight: bold; line-height: 1.6; text-align: right; border-right: 1px solid #ddd; }

.quoteblock blockquote { background: url('./images/blockquote-arrow.png?1372292342') 0 2px no-repeat; padding-left: 1em; }

.sidebarblock > .content > .title { margin-top: -20px; margin-right: -20px; margin-left: -20px; margin-bottom: 20px; padding: 1em; font-size: 0.8em; background: #eaeaea; }

body { background-image: url(./images/body-bg.jpg); }

pre, pre > code { color: #242424; }
.literalblock > .content pre, .listingblock > .content pre, .sidebarblock {background: url(./images/pre-bg.jpg);border-width: 0 0 1px 0;border-style: solid;border-color: #f0f0f0;-webkit-border-radius: 4px;border-radius: 4px;padding: 15px;word-wrap: break-word;}

.literalblock > .content > pre, .listingblock > .content > pre {-webkit-box-shadow: inset 0 1px 4px #aeb9b6;box-shadow: inset 0 1px 4px #aeb9b6;-webkit-border-radius: 5px;border-radius: 5px;}

*:not(pre)>code {white-space: nowrap;border: 1px solid #e1e1e8;color: #009;font-size: .875rem;font-family: Monaco, Menlo, Consolas, "Courier New", monospace;}

code {font-family: Monaco, Menlo, Consolas, "Courier New", monospace;font-weight: normal;color: #3d3d3c;word-break: break-word;}

table thead, table tfoot { background: #ebf2f2; font-weight: bold; }

table tr.even, table tr.alt, table tr:nth-child(even) { background: #f5f9f9; }

.admonitionblock.tip { background-color: #cfe7f1; }
.admonitionblock.note { background-color: #d2ebc0; }
.admonitionblock.warning { background-color: #f1e4b5; }
.admonitionblock.important { background-color: #f6d6d6; }
</style>
<!-- Generate a nice TOC -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery.tocify/1.9.0/javascripts/jquery.tocify.min.js"></script>
<!-- We do not need the tocify CSS because the asciidoc CSS already provides most of what we neeed -->

<style>
    .tocify ul {
        margin: 0;
    }

    .tocify-focus {
        color: #faa94c;
    }

    .tocify-focus > a {
        color: #faa94c;
    }
</style>

<script type="text/javascript">
    $(function () {
        // Add a new container for the tocify toc into the existing toc so we can re-use its
        // styling
        $("#toc").append("<div id='generated-toc'></div>");
        $("#generated-toc").tocify({
            extendPage: true,
            context: "#content",
            highlightOnScroll: true,
            hideEffect: "slideUp",
            // Use the IDs that asciidoc already provides so that TOC links and intra-document
            // links are the same. Anything else might confuse users when they create bookmarks.
            hashGenerator: function (text, element) {
                return $(element).attr("id");
            },
            // Smooth scrolling doesn't work properly if we use the asciidoc IDs
            smoothScroll: false,
            // Set to 'none' to use the tocify classes
            theme: "none",
            // Handle book (may contain h1) and article (only h2 deeper)
            selectors: $("#content").has("h1").size() > 0 ? "h1,h2,h3,h4,h5" : "h2,h3,h4,h5",
            ignoreSelector: ".discrete"
        });

        // Switch between static asciidoc toc and dynamic tocify toc based on browser size
        // This is set to match the media selectors in the asciidoc CSS
        // Without this, we keep the dynamic toc even if it is moved from the side to preamble
        // position which will cause odd scrolling behavior
        var handleTocOnResize = function () {
            if ($(document).width() < 768) {
                $("#generated-toc").hide();
                $(".sectlevel0").show();
                $(".sectlevel1").show();
            } else {
                $("#generated-toc").show();
                $(".sectlevel0").hide();
                $(".sectlevel1").hide();
            }
        }

        $(window).resize(handleTocOnResize);
        handleTocOnResize();
    });
</script>
</head>
<body class="article toc2 toc-left">
<div id="header">
<h1>Spring Cloud Config</h1>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_快速开始">快速开始</a>
<ul class="sectlevel2">
<li><a href="#_客户端使用">客户端使用</a></li>
</ul>
</li>
<li><a href="#_spring_cloud_config_服务器端">Spring Cloud Config 服务器端</a>
<ul class="sectlevel2">
<li><a href="#_环境仓库">环境仓库</a></li>
<li><a href="#_健康指标">健康指标</a></li>
<li><a href="#_安全">安全</a></li>
<li><a href="#_加密与解密">加密与解密</a></li>
<li><a href="#_密钥的管理">密钥的管理</a></li>
<li><a href="#_为测试创建一个密钥库">为测试创建一个密钥库</a></li>
<li><a href="#_使用多个密钥和密钥_rotation">使用多个密钥和密钥 Rotation</a></li>
<li><a href="#_提供加密的属性">提供加密的属性</a></li>
</ul>
</li>
<li><a href="#_提供可选择格式">提供可选择格式</a></li>
<li><a href="#_提供纯文本">提供纯文本</a>
<ul class="sectlevel2">
<li><a href="#spring-cloud-config-serving-plain-text-git-svn-native-backends">Git、SVN 和本地后端</a></li>
<li><a href="#spring-cloud-config-serving-plain-text-aws-s3">AWS S3</a></li>
<li><a href="#_解密纯文本">解密纯文本</a></li>
</ul>
</li>
<li><a href="#_嵌入式配置服务器">嵌入式配置服务器</a></li>
<li><a href="#_推送通知和_spring_cloud_bus">推送通知和 Spring Cloud Bus</a></li>
<li><a href="#_spring_cloud_config_客户端">Spring Cloud Config 客户端</a>
<ul class="sectlevel2">
<li><a href="#config-first-bootstrap">配置第一个 Bootstrap</a></li>
<li><a href="#discovery-first-bootstrap">发现第一个 Bootstrap</a></li>
<li><a href="#config-client-fail-fast">Config 客户端的快速失败</a></li>
<li><a href="#config-client-retry">Config 客户端的重试</a></li>
<li><a href="#_查找远程配置资源">查找远程配置资源</a></li>
<li><a href="#_为配置服务器指定多个地址">为配置服务器指定多个地址</a></li>
<li><a href="#_配置超时">配置超时</a></li>
<li><a href="#_安全_2">安全</a></li>
<li><a href="#_vault_中的嵌套密钥">Vault 中的嵌套密钥</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p><strong>2.2.3.RELEASE</strong></p>
</div>
<div class="paragraph">
<p>Spring Cloud Config 为分布式系统中外部化的配置提供了服务器端和客户端的支持。使用 Config Server，您可以在统一的位置管理所有环境中应用程序的外部属性。</p>
</div>
<div class="paragraph">
<p>客户端和服务器的概念与 Spring中 <code>Environment</code> 和 <code>PropertySource</code> 抽象对象完全相同，因此它非常适合Spring应用程序，而且可以与以任何语言运行的任何应用程序一起使用。应用程序从开发到测试再到部署生产的整个流程中，您都可以管理这些环境之间的配置，并确保应用程序已经拥有了它们迁移时所需的一切配置。</p>
</div>
<div class="paragraph">
<p>服务器存储后端的默认实现使用git，因此它轻松支持带标签的配置环境版本，并且可通过各种工具来访问以管理内容。通过Spring的配置，可以轻松的添加其它实现或是拔插。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_快速开始">快速开始</h2>
<div class="sectionbody">
<div class="paragraph">
<p>本章节会同时使用 Spring Cloud Config 的服务端和客户端。</p>
</div>
<div class="paragraph">
<p>首先，启动服务器，如下所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ cd spring-cloud-config-server
$ ../mvnw spring-boot:run</pre>
</div>
</div>
<div class="paragraph">
<p>服务端是一个 Spring Boot 程序，因此如果您愿意的话，也可以从IDE运行它（main class 是 <code>ConfigServerApplication</code> ）。</p>
</div>
<div class="paragraph">
<p>接下来试试客户端，如下所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ curl localhost:8888/foo/development
{"name":"foo","label":"master","propertySources":[
  {"name":"https://github.com/scratches/config-repo/foo-development.properties","source":{"bar":"spam"}},
  {"name":"https://github.com/scratches/config-repo/foo.properties","source":{"foo":"bar"}}
]}</pre>
</div>
</div>
<div class="paragraph">
<p>定位属性的默认策略是Git仓库策略（使用 <code>spring.cloud.config.server.git.uri</code> 配置Git地址）并使用它初始化一个小型 <code>SpringApplication</code> 应用。
小型应用的 <code>Environment</code> 用于枚举属性并将其发布在JSON端点上。</p>
</div>
<div class="listingblock">
<div class="content">
<pre>/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties</pre>
</div>
</div>
<div class="paragraph">
<p>在 <code>SpringApplication</code>（通常是常规Spring Boot应用程序中通常是 <code>application</code>）中，将应用程序以 <code>spring.config.name</code> 区分注入， <code>profile</code> 是激活的配置（或以逗号分隔的属性列表），而 <code>label</code> 是可选的git分支（ 默认为 <code>master</code> 。）</p>
</div>
<div class="paragraph">
<p>Spring Cloud Config Server 从各种来源为远程客户端提供配置。 以下示例从git存储库（必须提供）中获取配置，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo</code></pre>
</div>
</div>
<div class="paragraph">
<p>其他来源包括任何 与JDBC兼容的数据库，Subversion，Hashicorp Vault，Credhub 和本地文件系统。</p>
</div>
<div class="sect2">
<h3 id="_客户端使用">客户端使用</h3>
<div class="paragraph">
<p>要在应用程序中使用这些功能，您可以将其构建为依赖于 spring-cloud-config-client 的Spring Boot应用程序（例如，请参阅 config-client 或示例应用程序的测试用例）。 添加依赖项的最方便的方法是使用 Spring Boot starter <code>org.springframework.cloud:spring-cloud-starter-config</code>。
对于Maven用户，还有一个父pom 和 BOM（<code>spring-cloud-starter-parent</code>），对于 Gradle 和 Spring CLI 用户，还有一个 Spring IO 版本管理属性文件。 以下示例展示了典型的 Maven 配置：</p>
</div>
<div class="listingblock">
<div class="title">pom.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;parent&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
    &lt;version&gt;{spring-boot-docs-version}&lt;/version&gt;
    &lt;relativePath /&gt; &lt;!-- lookup parent from repository --&gt;
&lt;/parent&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
            &lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;
            &lt;version&gt;{spring-cloud-version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
        &lt;artifactId&gt;spring-cloud-starter-config&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
        &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;

&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

&lt;!-- repositories also needed for snapshots and milestones --&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>现在，您可以创建一个标准的 Spring Boot 应用程序，例如下面的HTTP服务器：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>@SpringBootApplication
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}</pre>
</div>
</div>
<div class="paragraph">
<p>当此HTTP服务器启动后，它将从端口8888上的默认本地配置服务器（如果正在运行）中获取外部配置。
要修改启动行为，可以使用 <code>bootstrap.properties</code> 更改配置服务器的位置（类似 <code>application.properties</code>，但用于应用程序上下文的引导阶段），如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>spring.cloud.config.uri: http://myconfigserver.com</pre>
</div>
</div>
<div class="paragraph">
<p>默认情况下，如果未设置应用程序名称，则将使用 <code>application</code>。 要修改这个名称，可以将以下属性添加到 <code>bootstrap.properties</code> 文件中：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>spring.application.name: myapp</pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
设置属性 <code>${spring.application.name}</code> 时，请不要在应用名称前加上保留字 <code>application-</code> 以防止解析正确的属性源时出现问题。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>引导程序属性在 <code>/env</code> 端点中显示为高优先级属性源，如以下示例所示。</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ curl localhost:8080/env
{
  "profiles":[],
  "configService:https://github.com/spring-cloud-samples/config-repo/bar.properties":{"foo":"bar"},
  "servletContextInitParams":{},
  "systemProperties":{...},
  ...
}</pre>
</div>
</div>
<div class="paragraph">
<p>名为 <code>configService:&lt;URL of remote repository&gt;/&lt;file name&gt;</code> 的属性源包含 <code>foo</code> 属性，其值为 <code>bar</code> ，并且是最高优先级。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
属性源名称中的URL是git存储库，而不是配置服务器URL。
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_spring_cloud_config_服务器端">Spring Cloud Config 服务器端</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Spring Cloud Config Server 为外部配置（键值对或等效的 YAML 内容）提供了一个基于HTTP资源的API。
通过使用 @EnableConfigServer 注解让服务器端嵌入到 Spring Boot 应用程序中。
以下就是配置服务器端的代码：</p>
</div>
<div class="listingblock">
<div class="title">ConfigServer.java</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
  public static void main(String[] args) {
    SpringApplication.run(ConfigServer.class, args);
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>像所有Spring Boot应用程序一样，它默认在端口8080上运行，但是您可以通过各种方式将其切换到更传统的端口8888。
最简单的方法也是设置默认配置仓库，方法是使用 <code>spring.config.name=configserver</code>（在 Config Server jar 中有一个 <code>configserver.yml</code>）启动它。
另一种方法是使用您自己的 <code>application.properties</code>，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="title">application.properties</div>
<div class="content">
<pre class="highlight"><code class="language-properties" data-lang="properties">server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo</code></pre>
</div>
</div>
<div class="paragraph">
<p>其中 <code>${user.home}/config-repo</code> 是包含YAML和属性文件的git仓库。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
在Windows上，如果文件URL带有前缀，则需要在文件URL中附加一个 "/"（例如，<code><a href="file:///${user.home}/config-repo" class="bare">file:///${user.home}/config-repo</a></code>）。
</td>
</tr>
</table>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
<div class="paragraph">
<p>下面显示了在前面的示例中创建 git 仓库的方法：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ cd $HOME
$ mkdir config-repo
$ cd config-repo
$ git init .
$ echo info.foo: bar &gt; application.properties
$ git add -A .
$ git commit -m "Add application.properties"</pre>
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<div class="title">Warning</div>
</td>
<td class="content">
将本地文件系统用于git仓库仅用于测试。 您应该在生产环境中使用服务器托管配置仓库。
</td>
</tr>
</table>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<div class="title">Warning</div>
</td>
<td class="content">
如果仅在其中存储文本文件，那么您的配置仓库在初始克隆时会非常快速高效。
如果在其中存储二进制文件（尤其是大文件），那么在首次配置请求时可能会非常慢，或者在服务器中遇到内存不足错误。
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="_环境仓库">环境仓库</h3>
<div class="paragraph">
<p>您应该在哪里存储配置服务器的配置文件？
控制此行为的策略是为 <code>Environment</code> 对象提供 <code>EnvironmentRepository</code>。
<code>Environment</code> 是Spring <code>Environment</code> 中的副本（包括 <code>propertySources</code> 作为主要功能）。
<code>Environment</code> 资源由三个变量参数化：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>{application}</code> ，它对应到客户端的 <code>spring.application.name</code>。</p>
</li>
<li>
<p><code>{profile}</code> ，它对应客户端的 <code>spring.profiles.active</code>（用逗号分隔的列表）。</p>
</li>
<li>
<p><code>{label}</code> ，这是服务器端功能，用于标记一组 "版本化" 的配置文件。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>仓库实现通常类似于Spring Boot应用程序，从参数 <code>spring.config.name</code> (等于 <code>{application}</code>) 和参数 <code>spring.profiles.active</code> (等于 <code>{profiles}</code>) 加载配置文件。
配置文件的优先规则也与常规Spring Boot应用程序中的规则相同：激活的 profile 优先于默认设置，并且，如果有多个 profile，则最后一个优先（类似于向 <code>Map</code> 添加键值对）。</p>
</div>
<div class="paragraph">
<p>以下示例为客户端应用程序初始化配置：</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  application:
    name: foo
  profiles:
    active: dev,mysql</code></pre>
</div>
</div>
<div class="paragraph">
<p>（与Spring Boot应用程序一样，这些属性也可以由环境变量或命令行参数设置）。</p>
</div>
<div class="paragraph">
<p>如果仓库基于文件，则服务器从 <code>application.yml</code>（在所有客户端之间共享）和 <code>foo.yml</code>（以foo.yml优先）创建 <code>Environment</code>。
如果YAML文件中包含指向 Spring profile 的属性，则会以更高的优先级来应用（按列出 profile 的顺序）。
如果存在特定于 profile 文件的YAML（或属性）文件，这些文件也将以比默认文件更高的优先级应用。
较高的优先级会转换为 <code>Environment</code> 中前面列出的 <code>PropertySource</code>。
（这些规则适用于独立的Spring Boot应用程序。）</p>
</div>
<div class="paragraph">
<p>您可以将 spring.cloud.config.server.accept-empty 设置为 false，以便在未找到应用程序的情况下404状态。
默认情况下，此标志设置为true。</p>
</div>
<div class="sect3">
<h4 id="_git_后端">Git 后端</h4>
<div class="paragraph">
<p><code>EnvironmentRepository</code> 的默认实现使用Git后端，这对于管理升级和物理环境以及审核更改非常方便。
要更改仓库的位置，可以在Config Server中设置 <code>spring.cloud.config.server.git.uri</code> 配置属性（例如，在 <code>application.yml</code> 中）。
如果使用<code>file</code>：前缀设置它，则它应该在本地仓库中运行，以便无需服务器即可快速轻松地开始使用。但是，在这种情况下，服务器无需克隆即可直接在本地仓库上运行（如果它不是裸露的，这并不重要，因为Config Server从不对"远程"仓库进行更改）。
要扩展Config Server并使其高可用，您需要使服务器的所有实例都指向同一仓库，因此仅共享文件系统可以工作。
即使在那种情况下，最好对共享文件系统仓库使用<code>ssh</code>：协议，以便服务器可以克隆它并将本地工作副本用作缓存。</p>
</div>
<div class="paragraph">
<p>此仓库实现将HTTP资源的<code>{label}</code>参数映射到git标签（提交ID，分支名称或标签）。
如果git分支或标记名称包含斜杠（<code>/</code>），则应使用特殊字符串 <code>(_)</code> 来指定HTTP URL中的标签（以避免与其他URL路径产生歧义）。
例如，如果 label 为 <code>foo/bar</code> ，则替换斜杠将产生以下 label ：<code>foo(_)bar</code>。
特殊字符串 <code>(_)</code> 的包含也可以应用于 <code>{application}</code> 参数。
如果使用curl之类的命令行客户端，请注意URL中的括号-您应使用单引号（''）将其从外壳中移出。</p>
</div>
<div class="sect4">
<h5 id="_忽略_ssl_证书验证">忽略 SSL 证书验证</h5>
<div class="paragraph">
<p>可以通过将 <code>git.skipSslValidation</code> 属性设置为 <code>true</code>（默认值为 <code>false</code>）来禁用配置服务器对 Git 服务器 SSL 证书的验证。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://example.com/my/repo
          skipSslValidation: true</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_配置_http_连接超时时间">配置 HTTP 连接超时时间</h5>
<div class="paragraph">
<p>您可以使用 <code>git.timeout</code> 属性配置配置服务器等待获取HTTP连接的时间（以秒为单位）。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://example.com/my/repo
          timeout: 4</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_git_uri_中的占位符">Git URI 中的占位符</h5>
<div class="paragraph">
<p>Spring Cloud Config Server 支持带有 <code>{application}</code> 和 <code>{profile}</code> （如果需要的话还有 <code>{label}</code>）占位符的 git 仓库URL，但是请记住，无论如何该标签都被用作 git 标签。
因此，您可以通过使用类似于以下内容的结构来支持 <code>"每个应用程序一个仓库"</code> 策略：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/myorg/{application}</code></pre>
</div>
</div>
<div class="paragraph">
<p>您也可以使用类似的模式（使用 <code>{profile}</code>）来支持 <code>"每个profile一个仓库"</code> 策略。</p>
</div>
<div class="paragraph">
<p>此外，在 <code>{application}</code> 参数中使用特殊字符串 "(_)" 可以启用对多个组织的支持，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/{application}</code></pre>
</div>
</div>
<div class="paragraph">
<p>其中 <code>{application}</code> 是在请求时以以下格式提供的：<code>organization(_)application</code>。</p>
</div>
</div>
<div class="sect4">
<h5 id="_正则匹配和多个仓库">正则匹配和多个仓库</h5>
<div class="paragraph">
<p>Spring Cloud Config 还通过在应用程序和配置文件名称上进行模式匹配来支持更复杂的需求。
匹配格式是 <code>{application}/{profile}</code> 逗号分隔的名称列表，带有通配符（请注意，以通配符开头的模式可能需要加引号），如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            simple: https://github.com/simple/config-repo
            special:
              pattern: special*/dev*,*special*/dev*
              uri: https://github.com/special/config-repo
            local:
              pattern: local*
              uri: file:/home/configsvc/config-repo</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果 <code>{application}/{profile}</code> 与任何模式都不匹配，它将使用在 <code>spring.cloud.config.server.git.uri</code> 下定义的默认URI。
在上面的示例中，对于 <code>"简单"</code> 仓库，模式为 <code>simple/*</code>（它仅与所有概要文件中一个名为 <code>simple</code> 的应用程序匹配）。
<code>"本地"</code> 仓库匹配所有概要文件中以 <code>local</code> 开头的所有应用程序名称（<code>/*</code> 后缀会自动添加到没有概要文件匹配器的任何模式中）。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
仅当要设置的唯一属性是URI时，才可以使用 <code>"简单"</code> 示例中使用的 <code>"单线"</code> 快捷方式。
如果您需要设置其他任何内容（凭证，匹配等），则需要使用完整表格。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>仓库中的 <code>pattern</code> 属性实际上是一个数组，因此您可以使用YAML数组（或属性文件中的 <code>[0]</code>，<code>[1]</code> 等后缀）绑定到多个模式。
如果要运行具有多个 profiles 文件的应用程序，则可能需要这样做，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            development:
              pattern:
                - '*/development'
                - '*/staging'
              uri: https://github.com/development/config-repo
            staging:
              pattern:
                - '*/qa'
                - '*/production'
              uri: https://github.com/staging/config-repo</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Spring Cloud 猜测包含不以 <code>*</code> 结尾的配置文件的模式意味着您实际上要匹配以该模式开头的配置文件列表（因此 <code>*/staging</code> 是 <code>["*/staging", "*/staging,*"]</code>， 等等）。
这很普遍，例如，您需要在本地的 <code>"development"</code> 配置文件中运行应用程序，而又需要在远程的 <code>"云"</code> 配置文件中运行应用程序。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>每个仓库还可以选择将配置文件存储在子目录中，并且可以将搜索这些目录的模式指定为 <code>searchPaths</code>。
下面的示例显示了一个顶层的配置文件：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          searchPaths: foo,bar*</code></pre>
</div>
</div>
<div class="paragraph">
<p>在前面的示例中，服务器在顶层，<code>foo/</code> 子目录以及名称以 <code>bar</code> 开头的任何子目录中搜索配置文件。</p>
</div>
<div class="paragraph">
<p>默认情况下，第一次请求配置时，服务器会克隆远程仓库。
可以将服务器配置为在启动时克隆仓库，如以下顶级示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://git/common/config-repo.git
          repos:
            team-a:
                pattern: team-a-*
                cloneOnStart: true
                uri: https://git/team-a/config-repo.git
            team-b:
                pattern: team-b-*
                cloneOnStart: false
                uri: https://git/team-b/config-repo.git
            team-c:
                pattern: team-c-*
                uri: https://git/team-a/config-repo.git</code></pre>
</div>
</div>
<div class="paragraph">
<p>在上述示例中，服务器会在启动时(接受任何请求之前)克隆 team-a 的 config-repo 。
在请求从仓库进行配置之前，不会克隆所有其他仓库。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
设置要在 Config Server 启动时克隆的仓库，可以帮助在 Config Server 启动时快速识别配置错误的配置源（例如无效的仓库URI）。
在未为配置源启用 <code>cloneOnStart</code> 的情况下，Config Server 可能会以配置错误或无效的配置源成功启动，并且直到应用程序从该配置源请求配置时才检测到错误。
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_认证">认证</h5>
<div class="paragraph">
<p>要在远程仓库上使用HTTP基本认证，请分别添加 <code>username</code> 和 <code>password</code> 属性（不在URL中），如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          username: trolley
          password: strongpassword</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果您不使用 HTTPS 和用户凭据，则在将密钥存储在默认目录（<code>~/.ssh</code>）中且URI指向SSH位置（例如 <code>git@github.com:configuration/cloud-configuration</code>。
在 <code>~/.ssh/known_hosts</code> 文件中存在Git服务器的条目，并采用 <code>ssh-rsa</code> 格式，这一点很重要。
不支持其他格式（例如 <code>ecdsa-sha2-nistp256</code>）。
为避免意外，您应该确保Git服务器的 <code>known_hosts</code> 文件中只有一个条目，并且该条目与您提供给配置服务器的URL匹配。
如果在URL中使用主机名，则希望在 <code>known_hosts</code> 文件中具有该主机名（而不是IP）。
使用JGit访问仓库，因此您找到的任何文档都应该适用。
HTTPS代理设置可以在 <code>~/.git/config</code> 或（与任何其他JVM进程相同的方式）通过系统属性（<code>-Dhttps.proxyHost</code> 和 <code>-Dhttps.proxyPort</code>）进行设置。</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
如果您不知道 <code>~/.git</code> 目录在哪里，请使用 <code>git config --global</code> 来操纵设置（例如，<code>git config --global http.sslVerify false</code>）。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>JGit 需要 PEM 格式的 RSA 密钥。 下面是一个示例 ssh-keygen（来自openssh）命令，它将以 corect 格式生成一个密钥：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">ssh-keygen -m PEM -t rsa -b 4096 -f ~/config_server_deploy_key.rsa</code></pre>
</div>
</div>
<div class="paragraph">
<p>Warning: 使用SSH密钥时，预期的ssh私钥必须以 <code><code>-----BEGIN RSA PRIVATE KEY-----</code></code> 开头。
如果密钥以 <code><code>-----BEGIN OPENSSH PRIVATE KEY-----</code></code> 开头，那么启动 spring-cloud-config 服务器时不会加载RSA密钥。
其错误看起来像这样：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>- Error in object 'spring.cloud.config.server.git': codes [PrivateKeyIsValid.spring.cloud.config.server.git,PrivateKeyIsValid]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.cloud.config.server.git.,]; arguments []; default message []]; default message [Property 'spring.cloud.config.server.git.privateKey' is not a valid private key]</code></pre>
</div>
</div>
<div class="paragraph">
<p>要更正以上错误，必须将RSA密钥转换为PEM格式。 上面提供了使用openssh的示例，用于以适当的格式生成新密钥。</p>
</div>
</div>
<div class="sect4">
<h5 id="_aws_codecommit_认证">AWS CodeCommit 认证</h5>
<div class="paragraph">
<p>Spring Cloud Config Server also supports <a href="https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html">AWS CodeCommit</a> authentication.
AWS CodeCommit uses an authentication helper when using Git from the command line.
This helper is not used with the JGit library, so a JGit CredentialProvider for AWS CodeCommit is created if the Git URI matches the AWS CodeCommit pattern.
AWS CodeCommit URIs follow this pattern://git-codecommit.${AWS_REGION}.amazonaws.com/${repopath}.</p>
</div>
<div class="paragraph">
<p>If you provide a username and password with an AWS CodeCommit URI, they must be the <a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html">AWS accessKeyId and secretAccessKey</a> that provide access to the repository.
If you do not specify a username and password, the accessKeyId and secretAccessKey are retrieved by using the <a href="https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html">AWS Default Credential Provider Chain</a>.</p>
</div>
<div class="paragraph">
<p>If your Git URI matches the CodeCommit URI pattern (shown earlier), you must provide valid AWS credentials in the username and password or in one of the locations supported by the default credential provider chain.
AWS EC2 instances may use <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html">IAM Roles for EC2 Instances</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The <code>aws-java-sdk-core</code> jar is an optional dependency.
If the <code>aws-java-sdk-core</code> jar is not on your classpath, the AWS Code Commit credential provider is not created, regardless of the git server URI.
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_google_cloud_source_认证">Google Cloud Source 认证</h5>
<div class="paragraph">
<p>Spring Cloud Config Server also supports authenticating against <a href="https://cloud.google.com/source-repositories/">Google Cloud Source</a> repositories.</p>
</div>
<div class="paragraph">
<p>If your Git URI uses the <code>http</code> or <code>https</code> protocol and the domain name is <code>source.developers.google.com</code>, the Google Cloud Source credentials provider will be used. A Google Cloud Source repository URI has the format <code><a href="https://source.developers.google.com/p/${GCP_PROJECT}/r/${REPO}" class="bare">https://source.developers.google.com/p/${GCP_PROJECT}/r/${REPO}</a></code>. To obtain the URI for your repository, click on "Clone" in the Google Cloud Source UI, and select "Manually generated credentials". Do not generate any credentials, simply copy the displayed URI.</p>
</div>
<div class="paragraph">
<p>The Google Cloud Source credentials provider will use Google Cloud Platform application default credentials. See <a href="https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login">Google Cloud SDK documentation</a> on how to create application default credentials for a system. This approach will work for user accounts in dev environments and for service accounts in production environments.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>com.google.auth:google-auth-library-oauth2-http</code> is an optional dependency.
If the <code>google-auth-library-oauth2-http</code> jar is not on your classpath, the Google Cloud Source credential provider is not created, regardless of the git server URI.
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_使用属性对_git_ssh_进行配置">使用属性对 Git SSH 进行配置</h5>
<div class="paragraph">
<p>默认情况下，当通过SSH URI连接到Git仓库时，Spring Cloud Config Server使用的JGit库使用SSH配置文件，例如 <code>~/.ssh/known_hosts</code> 和  <code>/etc/ssh/ssh_config</code>。
在Cloud Foundry之类的云环境中，本地文件系统可能是临时的，或者不容易访问。
对于那些情况，可以使用Java属性设置SSH配置。
为了激活基于属性的SSH配置，必须将 <code>spring.cloud.config.server.git.ignoreLocalSshSettings</code>  属性设置为 <code>true</code>，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">  spring:
    cloud:
      config:
        server:
          git:
            uri: git@gitserver.com:team/repo1.git
            ignoreLocalSshSettings: true
            hostKey: someHostKey
            hostKeyAlgorithm: ssh-rsa
            privateKey: |
                         -----BEGIN RSA PRIVATE KEY-----
                         MIIEpgIBAAKCAQEAx4UbaDzY5xjW6hc9jwN0mX33XpTDVW9WqHp5AKaRbtAC3DqX
                         IXFMPgw3K45jxRb93f8tv9vL3rD9CUG1Gv4FM+o7ds7FRES5RTjv2RT/JVNJCoqF
                         ol8+ngLqRZCyBtQN7zYByWMRirPGoDUqdPYrj2yq+ObBBNhg5N+hOwKjjpzdj2Ud
                         1l7R+wxIqmJo1IYyy16xS8WsjyQuyC0lL456qkd5BDZ0Ag8j2X9H9D5220Ln7s9i
                         oezTipXipS7p7Jekf3Ywx6abJwOmB0rX79dV4qiNcGgzATnG1PkXxqt76VhcGa0W
                         DDVHEEYGbSQ6hIGSh0I7BQun0aLRZojfE3gqHQIDAQABAoIBAQCZmGrk8BK6tXCd
                         fY6yTiKxFzwb38IQP0ojIUWNrq0+9Xt+NsypviLHkXfXXCKKU4zUHeIGVRq5MN9b
                         BO56/RrcQHHOoJdUWuOV2qMqJvPUtC0CpGkD+valhfD75MxoXU7s3FK7yjxy3rsG
                         EmfA6tHV8/4a5umo5TqSd2YTm5B19AhRqiuUVI1wTB41DjULUGiMYrnYrhzQlVvj
                         5MjnKTlYu3V8PoYDfv1GmxPPh6vlpafXEeEYN8VB97e5x3DGHjZ5UrurAmTLTdO8
                         +AahyoKsIY612TkkQthJlt7FJAwnCGMgY6podzzvzICLFmmTXYiZ/28I4BX/mOSe
                         pZVnfRixAoGBAO6Uiwt40/PKs53mCEWngslSCsh9oGAaLTf/XdvMns5VmuyyAyKG
                         ti8Ol5wqBMi4GIUzjbgUvSUt+IowIrG3f5tN85wpjQ1UGVcpTnl5Qo9xaS1PFScQ
                         xrtWZ9eNj2TsIAMp/svJsyGG3OibxfnuAIpSXNQiJPwRlW3irzpGgVx/AoGBANYW
                         dnhshUcEHMJi3aXwR12OTDnaLoanVGLwLnkqLSYUZA7ZegpKq90UAuBdcEfgdpyi
                         PhKpeaeIiAaNnFo8m9aoTKr+7I6/uMTlwrVnfrsVTZv3orxjwQV20YIBCVRKD1uX
                         VhE0ozPZxwwKSPAFocpyWpGHGreGF1AIYBE9UBtjAoGBAI8bfPgJpyFyMiGBjO6z
                         FwlJc/xlFqDusrcHL7abW5qq0L4v3R+FrJw3ZYufzLTVcKfdj6GelwJJO+8wBm+R
                         gTKYJItEhT48duLIfTDyIpHGVm9+I1MGhh5zKuCqIhxIYr9jHloBB7kRm0rPvYY4
                         VAykcNgyDvtAVODP+4m6JvhjAoGBALbtTqErKN47V0+JJpapLnF0KxGrqeGIjIRV
                         cYA6V4WYGr7NeIfesecfOC356PyhgPfpcVyEztwlvwTKb3RzIT1TZN8fH4YBr6Ee
                         KTbTjefRFhVUjQqnucAvfGi29f+9oE3Ei9f7wA+H35ocF6JvTYUsHNMIO/3gZ38N
                         CPjyCMa9AoGBAMhsITNe3QcbsXAbdUR00dDsIFVROzyFJ2m40i4KCRM35bC/BIBs
                         q0TY3we+ERB40U8Z2BvU61QuwaunJ2+uGadHo58VSVdggqAo0BSkH58innKKt96J
                         69pcVH/4rmLbXdcmNYGm6iu+MlPQk4BUZknHSmVHIFdJ0EPupVaQ8RHT
                         -----END RSA PRIVATE KEY-----</code></pre>
</div>
</div>
<div class="paragraph">
<p>下表描述了SSH配置属性。</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. SSH 配置属性</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">属性名</th>
<th class="tableblock halign-left valign-top">备注</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ignoreLocalSshSettings</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">如果为 <code>true</code>，请使用基于属性的SSH而非基于文件的SSH配置。 必须设置属性 <code>spring.cloud.config.server.git.ignoreLocalSshSettings</code> 中定义，而 <strong>不是</strong> 在仓库中定义。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>privateKey</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">有效的SSH私钥。 如果 <code>ignoreLocalSshSettings</code> 为 true 并且 Git URI 为 SSH 格式，则必须设置。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>hostKey</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">有效的SSH主机密钥。 如果还设置了 <code>hostKeyAlgorithm</code> ，则必须设置。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>hostKeyAlgorithm</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ssh-dss, ssh-rsa, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, or ecdsa-sha2-nistp521</code> 中的一种。 如果还设置了 <code>hostKey</code> ，则必须设置。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>strictHostKeyChecking</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code> 或 <code>false</code>。 如果为false，则忽略主机密钥错误。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>knownHostsFile</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">自定义 <code>.known_hosts</code> 文件的位置。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>preferredAuthentications</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">覆盖服务器身份验证方法顺序。 如果服务器在 <code>publickey</code> 方法之前具有键盘交互身份验证，则这应该可以避免登录提示。</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect4">
<h5 id="_git_search_paths_中的占位符">Git Search Paths 中的占位符</h5>
<div class="paragraph">
<p>Spring Cloud Config Server还支持带有 <code>{application}</code> 和 <code>{profile}</code>（如果需要，还有 <code>{label}</code> ）占位符的搜索路径，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          searchPaths: '{application}'</code></pre>
</div>
</div>
<div class="paragraph">
<p>上面的清单导致在仓库中搜索与目录（以及顶层）同名的文件。
通配符在带有占位符的搜索路径中也有效（搜索中包括任何匹配的目录）。</p>
</div>
</div>
<div class="sect4">
<h5 id="_git_仓库中的强行拉取">Git 仓库中的强行拉取</h5>
<div class="paragraph">
<p>如前所述，Spring Cloud Config Server会克隆远程git仓库，以防止污染本地副本（例如，操作系统进程更改了文件夹内容），使得Spring Cloud Config Server无法从远程仓库更新本地副本。</p>
</div>
<div class="paragraph">
<p>为了解决这个问题，有一个 <code>force-pull</code> 属性，如果本地副本被污染了，可以让 Spring Cloud Config Server 从远程仓库强制拉取，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          force-pull: true</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果您具有多个仓库配置，则可以为每个仓库单独配置 <code>force-pull</code> 属性，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://git/common/config-repo.git
          force-pull: true
          repos:
            team-a:
                pattern: team-a-*
                uri: https://git/team-a/config-repo.git
                force-pull: true
            team-b:
                pattern: team-b-*
                uri: https://git/team-b/config-repo.git
                force-pull: true
            team-c:
                pattern: team-c-*
                uri: https://git/team-a/config-repo.git</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>force-pull</code> 属性的默认值是 <code>false</code>.
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_删除_git_仓库中_untracked_的分支">删除 Git 仓库中 untracked 的分支</h5>
<div class="paragraph">
<p>由于Spring Cloud Config Server在将分支检出到本地仓库后（例如通过标签获取属性）具有远程git仓库的克隆，因此它将永久保留该分支或直到下一个服务器重启（这将创建新的本地仓库）。
因此，有可能删除远程分支，但仍可获取其本地副本。
而且，如果Spring Cloud Config Server客户端服务以 <code>--spring.cloud.config.label=deletedRemoteBranch,master</code> 开头，则主服务器将从 <code>deletedRemoteBranch</code> 本地分支而非 <code>master</code> 获取属性。</p>
</div>
<div class="paragraph">
<p>为了使本地仓库分支保持干净并和远程保持同步状态-可以设置 <code>deleteUntrackedBranches</code> 属性。
它将使Spring Cloud Config Server <strong>强制</strong> 从本地仓库中删除未跟踪的分支。 例：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          deleteUntrackedBranches: true</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>deleteUntrackedBranches</code> 属性的默认值是 <code>false</code>.
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_git_刷新率">Git 刷新率</h5>
<div class="paragraph">
<p>您可以使用 <code>spring.cloud.config.server.git.refreshRate</code> 控制配置服务器多久从Git后端获取更新的配置数据。 以秒为单位指定此属性的值。 默认情况下，该值为0，这意味着配置服务器将在每次请求时从Git仓库中获取更新的配置。</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_使用文件系统作为版本控制的后端">使用文件系统作为版本控制的后端</h4>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<div class="title">Warning</div>
</td>
<td class="content">
使用基于VCS的后端（git，svn），检出文件或将其克隆到本地文件系统。
默认情况下，它们以前缀 <code>config-repo-</code> 放置在系统临时目录中。
例如，在Linux上，它可能是 <code>/tmp/config-repo-&lt;randomid&gt;</code> 。 一些操作系统通常会 <a href="https://serverfault.com/questions/377348/when-does-tmp-get-cleared/377349#377349">定期清除</a> 临时目录。
这可能导致意外的行为，例如缺少属性。
为避免此问题，请通过将 <code>spring.cloud.config.server.git.basedir</code> 或 <code>spring.cloud.config.server.svn.basedir</code> 设置为不在系统临时结构中的目录来更改 Config Server 使用的目录。
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_文件系统后端">文件系统后端</h4>
<div class="paragraph">
<p>Config Server 中还有一个 <code>"native"</code> 配置文件，该配置文件不使用Git，而是从本地类路径或文件系统（您要使用 <code>spring.cloud.config.server.native.searchLocations</code> 指向的任何静态URL）加载配置文件。
要使用本机配置文件，请使用 <code>spring.profiles.active=native</code> 启动Config Server。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
切记对文件资源使用 <code>file:</code> 前缀（默认情况下，没有前缀的通常是类路径）。
与其它Spring Boot配置类似，您可以嵌入 <code>${}</code> 样式的环境占位符，但是请记住Windows中的绝对路径需要一个额外的  <code>/</code>（例如，<code><a href="file:///${user.home}/config-repo" class="bare">file:///${user.home}/config-repo</a></code>）。
</td>
</tr>
</table>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<div class="title">Warning</div>
</td>
<td class="content">
<code>searchLocations</code> 的默认值与本地Spring Boot应用程序相同（即 <code>[classpath:/, classpath:/config, file:./, file:./config]</code>）。
这不会将 <code>application.properties</code> 从服务器公开给所有客户端，因为服务器中存在的所有属性源在发送给客户端之前都已被删除。
</td>
</tr>
</table>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
文件系统后端非常适合快速入门和测试。 要在生产环境中使用它，您需要确保文件系统可靠并且可以在Config Server的所有实例之间共享。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>搜索位置可以包含 <code>{application}</code>，<code>{profile}</code> 和 <code>{label}</code> 的占位符。
这样，您可以隔离路径中的目录并选择对您有意义的策略（例如，每个应用程序的子目录或每个配置文件的子目录）。</p>
</div>
<div class="paragraph">
<p>如果您在搜索位置中不使用占位符，则此仓库还将HTTP资源的 <code>{label}</code> 参数附加到搜索路径上的后缀，
因此将从每个搜索位置 <code>和</code> 与该标签（在Spring环境中，带标签的属性优先）名称同名的子目录加载属性文件。
因此，没有占位符的默认行为与添加以 <code>/{label}/</code> 结尾的搜索位置相同。
例如，文件： <code>file:/tmp/config</code> 与文件： <code>file:/tmp/config,file:/tmp/config/{label}</code> 相同。
可以通过设置 <code>spring.cloud.config.server.native.addLabelLocations=false</code> 来禁用此行为。</p>
</div>
</div>
<div class="sect3">
<h4 id="vault-backend">Vault 后端</h4>
<div class="paragraph">
<p>Spring Cloud Config 服务器端还支持将 <a href="https://www.vaultproject.io">Vault</a> 作为后端。</p>
</div>
<div class="sidebarblock">
<div class="content">
<div class="paragraph">
<p>Vault is a tool for securely accessing secrets.
A secret is anything that to which you want to tightly control access, such as API keys, passwords, certificates, and other sensitive information. Vault provides a unified interface to any secret while providing tight access control and recording a detailed audit log.</p>
</div>
</div>
</div>
<div class="paragraph">
<p>For more information on Vault, see the <a href="https://learn.hashicorp.com/vault/?track=getting-started#getting-started">Vault quick start guide</a>.</p>
</div>
<div class="paragraph">
<p>To enable the config server to use a Vault backend, you can run your config server with the <code>vault</code> profile.
For example, in your config server&#8217;s <code>application.properties</code>, you can add <code>spring.profiles.active=vault</code>.</p>
</div>
<div class="paragraph">
<p>By default, the config server assumes that your Vault server runs at <code><a href="http://127.0.0.1:8200" class="bare">http://127.0.0.1:8200</a></code>.
It also assumes that the name of backend is <code>secret</code> and the key is <code>application</code>.
All of these defaults can be configured in your config server&#8217;s <code>application.properties</code>.
The following table describes configurable Vault properties:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Default Value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">host</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">127.0.0.1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">port</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">8200</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">scheme</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">http</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">backend</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">secret</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">defaultKey</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">application</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">profileSeparator</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">,</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">kvVersion</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">skipSslValidation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">timeout</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">namespace</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">null</p></td>
</tr>
</tbody>
</table>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
All of the properties in the preceding table must be prefixed with <code>spring.cloud.config.server.vault</code> or placed in the correct Vault section of a composite configuration.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>All configurable properties can be found in <code>org.springframework.cloud.config.server.environment.VaultEnvironmentProperties</code>.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
Vault 0.10.0 introduced a versioned key-value backend (k/v backend version 2) that exposes a different API than earlier versions, it now requires a <code>data/</code> between the mount path and the actual context path and wraps secrets in a <code>data</code> object. Setting <code>spring.cloud.config.server.vault.kv-version=2</code> will take this into account.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Optionally, there is support for the Vault Enterprise <code>X-Vault-Namespace</code> header. To have it sent to Vault set the <code>namespace</code> property.</p>
</div>
<div class="paragraph">
<p>With your config server running, you can make HTTP requests to the server to retrieve
values from the Vault backend.
To do so, you need a token for your Vault server.</p>
</div>
<div class="paragraph">
<p>First, place some data in you Vault, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">$ vault kv put secret/application foo=bar baz=bam
$ vault kv put secret/myapp foo=myappsbar</code></pre>
</div>
</div>
<div class="paragraph">
<p>Second, make an HTTP request to your config server to retrieve the values, as shown in the following example:</p>
</div>
<div class="paragraph">
<p><code>$ curl -X "GET" "http://localhost:8888/myapp/default" -H "X-Config-Token: yourtoken"</code></p>
</div>
<div class="paragraph">
<p>You should see a response similar to the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-json" data-lang="json">{
   "name":"myapp",
   "profiles":[
      "default"
   ],
   "label":null,
   "version":null,
   "state":null,
   "propertySources":[
      {
         "name":"vault:myapp",
         "source":{
            "foo":"myappsbar"
         }
      },
      {
         "name":"vault:application",
         "source":{
            "baz":"bam",
            "foo":"bar"
         }
      }
   ]
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The default way for a client to provide the necessary authentication to let Config Server talk to Vault is to set the X-Config-Token header.
However, you can instead omit the header and configure the authentication in the server, by setting the same configuration properties as Spring Cloud Vault.
The property to set is <code>spring.cloud.config.server.vault.authentication</code>.
It should be set to one of the supported authentication methods.
You may also need to set other properties specific to the authentication method you use, by using the same property names as documented for <code>spring.cloud.vault</code> but instead using the <code>spring.cloud.config.server.vault</code> prefix.
See the <a href="https://cloud.spring.io/spring-cloud-vault/reference/html/#vault.config.authentication">Spring Cloud Vault Reference Guide</a> for more detail.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
If you omit the X-Config-Token header and use a server property to set the authentication, the Config Server application needs an additional dependency on Spring Vault to enable the additional authentication options.
See the <a href="https://docs.spring.io/spring-vault/docs/current/reference/html/#dependencies">Spring Vault Reference Guide</a> for how to add that dependency.
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="_载入多个配置文件">载入多个配置文件</h5>
<div class="paragraph">
<p>When using Vault, you can provide your applications with multiple properties sources.
For example, assume you have written data to the following paths in Vault:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">secret/myApp,dev
secret/myApp
secret/application,dev
secret/application</code></pre>
</div>
</div>
<div class="paragraph">
<p>Properties written to <code>secret/application</code> are available to <a href="#_vault_server">all applications using the Config Server</a>.
An application with the name, <code>myApp</code>, would have any properties written to <code>secret/myApp</code> and <code>secret/application</code> available to it.
When <code>myApp</code> has the <code>dev</code> profile enabled, properties written to all of the above paths would be available to it, with properties in the first path in the list taking priority over the others.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_通过代理访问后端">通过代理访问后端</h4>
<div class="paragraph">
<p>配置服务器可以通过HTTP或HTTPS代理访问Git或Vault后端。
对于Git或保险柜，此行为是通过 <code>proxy.http</code> 和 <code>proxy.https</code> 下的设置控制的。
这些设置是针对每个仓库的，因此，如果您使用 <a href="#composite-environment-repositories">复杂多环境仓库</a> ，则必须分别为组合中的每个后端配置代理。
如果使用的网络需要HTTP和HTTPS URL使用代理服务器，则可以为单个后端配置HTTP和HTTPS代理设置。</p>
</div>
<div class="paragraph">
<p>下表描述了HTTP和HTTPS代理的代理配置属性。 所有这些属性都必须以 <code>proxy.http</code> 或 <code>proxy.https</code> 作为前缀。</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 2. 代理配置属性</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">属性名</th>
<th class="tableblock halign-left valign-top">备注</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>host</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">代理的主机。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>port</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">用于访问代理的端口。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nonProxyHosts</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">配置服务器应在代理外部访问的所有主机。 如果同时为 <code>proxy.http.nonProxyHosts</code> 和 <code>proxy.https.nonProxyHosts</code> 提供值，则可以用到 <code>proxy.http</code> 属性。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>username</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">用来验证代理的用户名。 如果同时为 <code>proxy.http.username</code> 和 <code>proxy.https.username</code> 提供了值，则将使用 <code>proxy.http</code> 值。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>password</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">用来验证代理的密码。 如果同时为 <code>proxy.http.password</code> 和 <code>proxy.https.password</code> 提供值，则将使用 <code>proxy.http</code> 值。</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>以下配置使用HTTPS代理访问Git仓库。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  profiles:
    active: git
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          proxy:
            https:
              host: my-proxy.host.io
              password: myproxypassword
              port: '3128'
              username: myproxyusername
              nonProxyHosts: example.com</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_与所有应用程序共享配置">与所有应用程序共享配置</h4>
<div class="paragraph">
<p>所有应用程序之间的共享配置根据您采用的方法而异，如以下主题所述：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#spring-cloud-config-server-file-based-repositories">基于文件的仓库</a></p>
</li>
<li>
<p><a href="#spring-cloud-config-server-vault-server">Vault 服务器</a></p>
</li>
</ul>
</div>
<div class="sect4">
<h5 id="spring-cloud-config-server-file-based-repositories">基于文件的仓库</h5>
<div class="paragraph">
<p>使用基于文件的（git、svn和本机）仓库，在所有客户端应用程序之间共享具有 <code>application*</code>（<code>application.properties</code>, <code>application.yml</code>, <code>application-*.properties</code> 等）中文件名的资源。
您可以使用具有这些文件名的资源来配置全局默认值，并在需要时使用特定于应用程序的文件覆盖它们。</p>
</div>
<div class="paragraph">
<p><a href="#property-overrides">属性的覆盖</a> 功能也可用于设置全局默认值，允许应用程序使用占位符在本地覆盖它们。</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
通过 <code>"本机"</code> 配置文件（本地文件系统后端），您应该使用不属于服务器自身配置的显式搜索位置。
否则，默认搜索位置中的 <code>application</code> 资源将被删除，因为它们是服务器的一部分。
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="spring-cloud-config-server-vault-server">Vault 服务器</h5>
<div class="paragraph">
<p>将 Vault 用作后端时，可以通过将配置放置在 <code>secret/application</code> 中来与所有应用程序共享配置。
例如，如果您运行以下Vault命令，则使用配置服务器的所有应用程序将具有对它们可用的属性 <code>foo</code> 和 <code>baz</code>：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">$ vault write secret/application foo=bar baz=bam</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_credhub_服务器">CredHub 服务器</h5>
<div class="paragraph">
<p>将CredHub用作后端时，可以通过将配置放在 <code>/application/</code> 中或将其放在应用程序的 <code>default</code> 配置文件中来与所有应用程序共享配置。
例如，如果运行以下CredHub命令，则所有使用配置服务器的应用程序都将具有属性 <code>shared.color1</code> 和 <code>shared.color2</code> 可供使用：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">credhub set --name "/application/profile/master/shared" --type=json
value: {"shared.color1": "blue", "shared.color": "red"}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">credhub set --name "/my-app/default/master/more-shared" --type=json
value: {"shared.word1": "hello", "shared.word2": "world"}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_jdbc_后端">JDBC 后端</h4>
<div class="paragraph">
<p>Spring Cloud Config Server 支持 JDBC（关系型数据库）作为配置属性的后端。
您可以通过将 <code>spring-jdbc</code> 添加到类路径并使用 <code>jdbc</code> 概要文件或通过添加类型为 <code>JdbcEnvironmentRepository</code> 的bean来启用此功能。
如果您在类路径上包括正确的依赖项（有关更多详细信息，请参见 <a href="https://spring.io/guides/gs/relational-data-access/">用户指南</a>），Spring Boot会配置数据源。</p>
</div>
<div class="paragraph">
<p>数据库需要有一个名为 <code>PROPERTIES</code> 的表，该表的列名为 <code>APPLICATION</code>，<code>PROFILE</code> 和 <code>LABEL</code>（具有通常的 <code>环境</code> 含义），以及 <code>Properties</code> 样式中的键值对使用<code>KEY</code>和<code>VALUE</code>。
在Java中，所有字段的类型均为String，因此您可以将它们设为所需长度的 <code>VARCHAR</code>。
属性值的行为方式与它们来自名为 <code>{application}-{profile}.properties</code> 的Spring Boot属性文件的行为相同，包括所有加密和解密，它们将用作后处理步骤（即， 在仓库中直接执行）。</p>
</div>
</div>
<div class="sect3">
<h4 id="_redis_后端">Redis 后端</h4>
<div class="paragraph">
<p>Spring Cloud Config Server支持Redis作为配置属性的后端。
您可以通过向 <a href="https://spring.io/projects/spring-data-redis">Spring Data Redis</a> 添加依赖项来启用此功能。</p>
</div>
<div class="listingblock">
<div class="title">pom.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-data-redis&lt;/artifactId&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>以下配置使用Spring Data <code>RedisTemplate</code> 访问Redis。 我们可以使用 <code>spring.redis.*</code> 属性覆盖默认的连接设置。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  profiles:
    active: redis
  redis:
    host: redis
    port: 16379</code></pre>
</div>
</div>
<div class="paragraph">
<p>这些属性应作为字段存储在哈希中。 哈希的名称应与 <code>spring.application.name</code> 属性相同，或与 <code>spring.application.name</code> 和 <code>spring.profiles.active[n]</code> 的结合。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">HMSET sample-app server.port "8100" sample.topic.name "test" test.property1 "property1"</code></pre>
</div>
</div>
<div class="paragraph">
<p>执行上面可见的命令后，哈希应包含：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>HGETALL sample-app
{
  "server.port": "8100",
  "sample.topic.name": "test",
  "test.property1": "property1"
}</pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
未指定配置文件时，将使用 <code>默认</code> 值。
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_aws_s3_后端">AWS S3 后端</h4>
<div class="paragraph">
<p>Spring Cloud Config Server supports AWS S3 as a backend for configuration properties.
You can enable this feature by adding a dependency to the <a href="https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/examples-s3.html">AWS Java SDK For Amazon S3</a>.</p>
</div>
<div class="listingblock">
<div class="title">pom.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependencies&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;com.amazonaws&lt;/groupId&gt;
		&lt;artifactId&gt;aws-java-sdk-s3&lt;/artifactId&gt;
	&lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The following configuration uses the AWS S3 client to access configuration files. We can use <code>spring.awss3.*</code> properties to select the bucket where your configuration is stored.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  profiles:
    active: awss3
  cloud:
    config:
      server:
        awss3:
          region: us-east-1
          bucket: bucket1</code></pre>
</div>
</div>
<div class="paragraph">
<p>It is also possible to specify an AWS URL to <a href="https://aws.amazon.com/blogs/developer/using-new-regions-and-endpoints/">override the standard endpoint</a> of your S3 service with <code>spring.awss3.endpoint</code>. This allows support for beta regions of S3, and other S3 compatible storage APIs.</p>
</div>
<div class="paragraph">
<p>Credentials are found using the <a href="https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html">Default AWS Credential Provider Chain</a>. Versioned and encrypted buckets are supported without further configuration.</p>
</div>
<div class="paragraph">
<p>Configuration files are stored in your bucket as <code>{application}-{profile}.properties</code>, <code>{application}-{profile}.yml</code> or <code>{application}-{profile}.json</code>. An optional label can be provided to specify a directory path to the file.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
When no profile is specified <code>default</code> will be used.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_credhub_后端">CredHub 后端</h4>
<div class="paragraph">
<p>Spring Cloud Config Server supports <a href="https://docs.cloudfoundry.org/credhub">CredHub</a> as a backend for configuration properties.
You can enable this feature by adding a dependency to <a href="https://spring.io/projects/spring-credhub">Spring CredHub</a>.</p>
</div>
<div class="listingblock">
<div class="title">pom.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependencies&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;org.springframework.credhub&lt;/groupId&gt;
		&lt;artifactId&gt;spring-credhub-starter&lt;/artifactId&gt;
	&lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The following configuration uses mutual TLS to access a CredHub:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  profiles:
    active: credhub
  cloud:
    config:
      server:
        credhub:
          url: https://credhub:8844</code></pre>
</div>
</div>
<div class="paragraph">
<p>The properties should be stored as JSON, such as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">credhub set --name "/demo-app/default/master/toggles" --type=json
value: {"toggle.button": "blue", "toggle.link": "red"}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">credhub set --name "/demo-app/default/master/abs" --type=json
value: {"marketing.enabled": true, "external.enabled": false}</code></pre>
</div>
</div>
<div class="paragraph">
<p>All client applications with the name <code>spring.cloud.config.name=demo-app</code> will have the following properties available to them:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>{
    toggle.button: "blue",
    toggle.link: "red",
    marketing.enabled: true,
    external.enabled: false
}</pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
When no profile is specified <code>default</code> will be used and when no label is specified <code>master</code> will be used as a default value.
NOTE: Values added to <code>application</code> will be shared by all the applications.
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="_oauth_2_0">OAuth 2.0</h5>
<div class="paragraph">
<p>You can authenticate with <a href="https://oauth.net/2/">OAuth 2.0</a> using <a href="https://docs.cloudfoundry.org/concepts/architecture/uaa.html">UAA</a> as a provider.</p>
</div>
<div class="listingblock">
<div class="title">pom.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependencies&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
		&lt;artifactId&gt;spring-security-config&lt;/artifactId&gt;
	&lt;/dependency&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
		&lt;artifactId&gt;spring-security-oauth2-client&lt;/artifactId&gt;
	&lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The following configuration uses OAuth 2.0 and UAA to access a CredHub:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  profiles:
    active: credhub
  cloud:
    config:
      server:
        credhub:
          url: https://credhub:8844
          oauth2:
            registration-id: credhub-client
  security:
    oauth2:
      client:
        registration:
          credhub-client:
            provider: uaa
            client-id: credhub_config_server
            client-secret: asecret
            authorization-grant-type: client_credentials
        provider:
          uaa:
            token-uri: https://uaa:8443/oauth/token</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The used UAA client-id should have <code>credhub.read</code> as scope.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="composite-environment-repositories">复杂多环境仓库</h4>
<div class="paragraph">
<p>在某些情况下，您可能希望从多个环境仓库中提取配置数据。
为此，您可以在配置服务器的应用程序属性或YAML文件中启用 <code>composite</code> (综合) 配置文件。
例如，如果要从Subversion仓库以及两个Git仓库中提取配置数据，则可以为配置服务器设置以下属性：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  profiles:
    active: composite
  cloud:
    config:
      server:
        composite:
        -
          type: svn
          uri: file:///path/to/svn/repo
        -
          type: git
          uri: file:///path/to/rex/git/repo
        -
          type: git
          uri: file:///path/to/walter/git/repo</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用此配置，优先级由 <code>composite</code> 键下仓库的列出顺序确定。
在上面的示例中，首先列出了Subversion仓库，因此在Subversion仓库中找到的值将覆盖在其中一个Git仓库中为同一属性找到的值。
在 <code>rex</code> Git仓库中找到的值将在 <code>walter</code> Git仓库中为相同属性找到的值之前使用。</p>
</div>
<div class="paragraph">
<p>如果您只想从各自不同类型的仓库中提取配置数据，则可以在配置服务器的应用程序属性或YAML文件中启用相应的配置文件，而不是复合配置文件。
例如，如果要从单个Git仓库和单个HashiCorp Vault服务器提取配置数据，则可以为配置服务器设置以下属性：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  profiles:
    active: git, vault
  cloud:
    config:
      server:
        git:
          uri: file:///path/to/git/repo
          order: 2
        vault:
          host: 127.0.0.1
          port: 8200
          order: 1</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用此配置，可以通过 <code>order</code> 属性确定优先级。
您可以使用 <code>order</code> 属性为所有仓库指定优先级顺序。
<code>order</code> 属性的数值越小，优先级越高。
仓库的优先级顺序有助于解决包含相同属性值的仓库之间的任何潜在冲突。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
如果您的复合环境包括上一个示例中的Vault服务器，则在对配置服务器的每个请求中都必须包含Vault令牌。 请参阅 <a href="#vault-backend">Vault 后端</a>。
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
从环境仓库中检索值时，任何类型的故障都会导致整个组合环境的故障。
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
使用复合环境时，所有仓库都包含相同的标签很重要。
如果您的环境与前面的示例中的环境类似，并且您请求带有 <code>master</code> 标签的配置数据，但是Subversion仓库不包含名为 <code>master</code> 的分支，则整个请求将失败。
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="_自定义多环境仓库">自定义多环境仓库</h5>
<div class="paragraph">
<p>除了使用Spring Cloud中的一个环境仓库之外，您还可以提供自己的 <code>EnvironmentRepository</code> bean，以将其作为复合环境的一部分包含在内。
为此，您的bean必须实现 <code>EnvironmentRepository</code> 接口。
如果要在复合环境中控制自定义 <code>EnvironmentRepository</code> 的优先级，则还应该实现 <code>Ordered</code> 接口并重写 <code>getOrdered</code> 方法。
如果未实现 <code>Ordered</code> 接口，则 <code>EnvironmentRepository</code> 的优先级最低。</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="property-overrides">属性的覆盖</h4>
<div class="paragraph">
<p>Config Server具有 <code>"overrides"</code> 功能，使操作人员可以为所有应用程序提供配置属性。
应用程序使用常规的Spring Boot钩子不会意外更改重写的属性。
要声明覆盖，请将名称/值对的映射添加到 <code>spring.cloud.config.server.overrides</code> ，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        overrides:
          foo: bar</code></pre>
</div>
</div>
<div class="paragraph">
<p>前面的示例使作为配置客户端的所有应用程序读取 <code>foo=bar</code>，而与它们自己的配置无关。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
配置系统不能强制应用程序以任何特定方式使用配置数据。 因此，覆盖无法强制执行。
但是，它们确实为Spring Cloud Config客户端提供了有用的默认行为。
</td>
</tr>
</table>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
通常，可以使用反斜杠（<code>\</code>）对 <code>$</code> 或 <code>{</code> 进行转义，从而对带有 <code>${}</code> 的Spring环境占位符进行转义（并在客户端上解析）。
例如，除非应用提供自己的 <code>app.foo</code>，否则 <code>\${app.foo:bar}</code> 解析为 <code>bar</code>。
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
在YAML中，您不需要转义反斜杠本身。
但是，当您需要在服务器上配置覆盖属性文件时，确实需要转义反斜杠。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>您可以通过在远程仓库中设置 <code>spring.cloud.config.overrideNone=true</code> 标志（默认值为false），将客户端中所有替代的优先级更改为更像默认值，让应用程序在环境变量或系统属性中提供自己的值。</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_健康指标">健康指标</h3>
<div class="paragraph">
<p>Config Server 提供了运行状况指示器，用于检查配置的 <code>EnvironmentRepository</code> 是否正常工作。
默认情况下，它向 <code>EnvironmentRepository</code> 询问名为 <code>app</code> 的应用程序，<code>默认</code> 配置文件和 <code>EnvironmentRepository</code> 实现提供的默认标签。</p>
</div>
<div class="paragraph">
<p>您可以配置运行状况指示器以检查更多应用程序以及自定义配置文件和自定义标签，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      server:
        health:
          repositories:
            myservice:
              label: mylabel
            myservice-dev:
              name: myservice
              profiles: development</code></pre>
</div>
</div>
<div class="paragraph">
<p>你可以通过设置 <code>spring.cloud.config.server.health.enabled=false</code> 来禁用运行状况指示器。</p>
</div>
</div>
<div class="sect2">
<h3 id="_安全">安全</h3>
<div class="paragraph">
<p>您可以用对您有意义的任何方式来保护Config Server（从物理网络安全到OAuth2承载令牌），因为Spring Security和Spring Boot提供了对许多安全性安排的支持。</p>
</div>
<div class="paragraph">
<p>要使用默认的Spring Boot配置的HTTP Basic安全性，请在类路径中包含Spring Security（例如，通过 <code>spring-boot-starter-security</code> ）。
默认用户名为 <code>user</code> ，密码则是随机生成。 随机密码实际上没有用，因此我们建议您配置密码（通过设置 <code>spring.security.user.password</code> ）并对其进行加密（有关如何执行此操作的说明，请参见下文）。</p>
</div>
</div>
<div class="sect2">
<h3 id="_加密与解密">加密与解密</h3>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
要使用加密和解密功能，您需要在JVM中安装完整的JCE（默认情况下是没有安装的）。
您可以从Oracle下载 <a href="https://www.oracle.com/java/technologies/javase-jce-all-downloads.html"><code>"Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files"</code></a> 并按照安装说明进行操作（总的说就是用下载的 <code>JRE lib/security</code> 目录替换这两个策略文件）。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>如果远程属性源包含加密的内容（以 <code>{cipher}</code> 开头的值），则将它们解密，然后再通过HTTP发送给客户端。
此设置的主要优点是，当属性值处于 <code>"at rest"</code> 状态时（例如，在git仓库中），不需要使用纯文本格式。
如果无法解密某个值，则将其从属性源中删除，并使用相同的密钥添加一个附加属性，但以 <code>invalid</code> 为前缀，并且该值表示 <code>"not applicable"</code>（通常为 <code>&lt;n/a&gt;</code>）。
这在很大程度上是为了防止密文用作密码并意外泄漏。</p>
</div>
<div class="paragraph">
<p>如果为配置客户端应用程序设置了远程配置仓库，则它的 <code>application.yml</code> 可能类似于以下内容：</p>
</div>
<div class="listingblock">
<div class="title">application.yml</div>
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  datasource:
    username: dbuser
    password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'</code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">application.properties</div>
<div class="content">
<pre>spring.datasource.username: dbuser
spring.datasource.password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ</pre>
</div>
</div>
<div class="paragraph">
<p>您可以安全地将此纯文本推送到共享的git仓库，并且密码仍然受到保护。</p>
</div>
<div class="paragraph">
<p>服务器还公开 <code>/encrypt</code> 和 <code>/decrypt</code> 端点（假设这些端点是安全的，并且只能由授权代理访问）。
如果您编辑远程配置文件，则可以使用Config Server通过POST到 <code>/encrypt</code> 端点来加密值，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ curl localhost:8888/encrypt -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda</pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
如果您加密的值中包含需要URL编码的字符，则应使用 <code>--data-urlencode</code> 选项进行 <code>curl</code> 以确保其编码正确。
</td>
</tr>
</table>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
确保不要在加密值中包含任何curl命令统计信息。 将值输出到文件可以帮助避免此问题。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>也可以通过 <code>/decrypt</code>（如果服务器配置了对称密钥或完整密钥对）来执行反向操作，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ curl localhost:8888/decrypt -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret</pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
如果使用 curl 进行测试，则使用 <code>--data-urlencode</code>（而不是 <code>-d</code>）或设置显式的 <code>Content-Type: text/plain</code> 以确保 curl 在存在特殊字符时正确编码数据（<code>+</code> 特别棘手） ）。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>在将加密的值放入YAML或属性文件之前，以及将其提交并将其推送到远程（可能不安全）存储之前，请获取加密的值并添加 <code>{cipher}</code> 前缀。</p>
</div>
<div class="paragraph">
<p><code>/encrypt</code> 和 <code>/decrypt</code> 端点也都接受 <code>/*/{application}/{profiles}</code> 形式的路径，当客户端调用时，可用于基于每个应用程序（名称）和每个配置文件控制密码 主要环境资源。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
要以这种精细的方式控制加密，还必须提供类型为 <code>TextEncryptorLocator</code> 的 <code>@Bean</code>，该 <code>@Bean</code> 的名称和配置文件将创建不同的加密器。
默认情况下不提供（所有加密使用相同的密钥）。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p><code>spring</code> 命令行客户端（安装了Spring Cloud CLI扩展）也可以用于加密和解密，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ spring encrypt mysecret --key foo
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret</pre>
</div>
</div>
<div class="paragraph">
<p>要使用文件中的密钥（例如用于加密的RSA公钥），请在密钥值前添加 "@" 并提供文件路径，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...</pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>--key</code> 参数是强制性的（尽管有 <code>--</code> 前缀）。
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_密钥的管理">密钥的管理</h3>
<div class="paragraph">
<p>Config Server可以使用对称（共享）密钥或非对称密钥（RSA密钥对）。
非对称选择在安全性方面优越，但是使用对称密钥通常更方便，因为它是在 <code>bootstrap.properties</code> 中配置的单个属性值。</p>
</div>
<div class="paragraph">
<p>要配置对称密钥，您需要将 <code>crypto.key</code> 设置为秘密字符串（或使用<code>ENCRYPT_KEY</code>环境变量将其保留在纯文本配置文件之外）。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
您不能使用<code>crypto.key</code>配置非对称密钥。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>要配置非对称密钥，请使用密钥库（例如，由JDK自带的<code>keytool</code>实用程序创建的密钥库）。
密钥库属性为 <code>encrypt.keyStore.*</code> ，其中<code>*</code>等于：</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-center valign-top">属性</th>
<th class="tableblock halign-center valign-top">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>encrypt.keyStore.location</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">包含<code>资源</code>位置</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>encrypt.keyStore.password</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">持有用于解锁密钥库的密码</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>encrypt.keyStore.alias</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">密钥库中要使用的ID</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>encrypt.keyStore.type</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">要创建的密钥库类型。 默认为<code>jks</code>。</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>加密是使用公钥完成的，解密需要私钥。
因此，原则上，如果您只想加密（并准备使用私钥在本地解密值），则只需在服务器中配置公钥。
实际上，您可能不希望在本地进行解密，因为它会将密钥管理过程分布在所有客户端上，而不是将其集中在服务器上。
另一方面，如果您的配置服务器相对不安全并且只有少数客户端需要加密的属性，那么它可能是一个有用的选项。</p>
</div>
</div>
<div class="sect2">
<h3 id="_为测试创建一个密钥库">为测试创建一个密钥库</h3>
<div class="paragraph">
<p>要创建用于测试的密钥库，可以使用类似于以下内容的命令：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ keytool -genkeypair -alias mytestkey -keyalg RSA \
  -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
  -keypass changeme -keystore server.jks -storepass letmein</pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
使用JDK 11或更高版本时，使用上述命令时可能会收到以下警告。 在这种情况下，您可能需要确保 <code>keypass</code> 和 <code>storepass</code> 的值匹配。
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre>Warning:  Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified -keypass value.</pre>
</div>
</div>
<div class="paragraph">
<p>将<code>server.jks</code>文件放入类路径（举例），然后在<code>bootstrap.yml</code>中为Config Server创建以下设置：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">encrypt:
  keyStore:
    location: classpath:/server.jks
    password: letmein
    alias: mytestkey
    secret: changeme</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_使用多个密钥和密钥_rotation">使用多个密钥和密钥 Rotation</h3>
<div class="paragraph">
<p>除了加密属性值中的 <code>{cipher}</code> 前缀之外，Config Server在（Base64编码的）密文开始之前查找零个或多个 <code>{name:value}</code> 前缀。
密钥被传递到<code>TextEncryptorLocator</code>，后者可以执行为密码找到<code>TextEncryptor</code>所需的任何逻辑。
如果已配置了密钥库（<code>encrypt.keystore.location</code>），则默认定位器将查找具有由<code>key</code>前缀提供的别名的密钥，其密文类似于以下内容：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">foo:
  bar: `{cipher}{key:testkey}...`</code></pre>
</div>
</div>
<div class="paragraph">
<p>定位器查找名为 "testkey" 的密钥。
也可以通过在前缀中使用 <code>{secret:&#8230;&#8203;}</code> 值来提供秘密。
但是，如果未提供，则默认为使用密钥库密码（这是在构建密钥库且未指定密钥时得到的密码）。
如果确实提供了机密，则还应该使用自定义的<code>SecretLocator</code>对机密进行加密。</p>
</div>
<div class="paragraph">
<p>当密钥仅用于加密几个字节的配置数据时（也就是说，它们未在其他地方使用），从密码的角度讲，几乎不需要旋转密钥。
但是，您有时可能需要更改密钥（例如，在发生安全漏洞时）。
在这种情况下，所有客户端都需要更改其源配置文件（例如，在git中），并在所有密码中使用新的 <code>{key:&#8230;&#8203;}</code> 前缀。
请注意，客户端需要首先检查Config Server密钥库中的密钥别名是否可用。</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
如果要让Config Server处理所有加密以及解密，还可以将 <code>{name:value}</code> 前缀作为纯文本添加到 <code>/encrypt</code> 终结点上。
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_提供加密的属性">提供加密的属性</h3>
<div class="paragraph">
<p>有时，您希望客户端在本地解密配置，而不是在服务器中进行解密。
在那种情况下，如果提供 <code>encrypt.*</code> 配置来定位密钥，则仍然可以具有 <code>/encrypt</code> 和 <code>/decrypt</code> 端点，但是您需要通过设置引导程序 <code>bootstrap.[yml|properties]</code> 中的 <code>spring.cloud.config.server.encrypt.enabled=false</code> 属性，来显式地关闭对传出属性的解密。
如果您不关心端点，则在不配置键或启用标志的情况下它都能正常使用。</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_提供可选择格式">提供可选择格式</h2>
<div class="sectionbody">
<div class="paragraph">
<p>环境端点中的默认JSON格式非常适合Spring应用程序使用，因为它直接映射到 <code>Environment</code> 抽象。
如果愿意，可以通过在资源路径中添加后缀（".yml", ".yaml" 或 ".properties"）来使用与YAML或Java属性相同的数据。
对于不关心JSON终结点的结构或它们提供的额外元数据的应用程序来说，这很有用（例如，不使用Spring的应用程序可能会受益于此方法的简单性）。</p>
</div>
<div class="paragraph">
<p>YAML和 properties 文件还有一个附加标志（提供一个叫 <code>resolvePlaceholders</code> 的布尔查询参数），以标记源文档中的占位符（标准Spring用的是 <code>${&#8230;&#8203;}</code> 形式）。
对于不了解Spring占位符约定的使用者来说，这是一个有用的功能。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
使用YAML或properties格式存在一些限制，主要是与元数据的丢失有关。
例如，JSON被构造为属性源的有序列表，其名称与该源相关。
即使值的来源有多个来源，YAML和properties格式也会合并到一个映射中，然后原始来源文件的名称就会丢失。
同样，YAML表示也不一定是后端仓库中YAML源的最终表示。 它由一系列平面属性来源构成，并且必须对密钥的形式进行假设。
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_提供纯文本">提供纯文本</h2>
<div class="sectionbody">
<div class="paragraph">
<p>您的应用程序可能不需要使用 <code>Environment</code> 抽象（或以YAML或properties格式使用其抽象表示之一），而需要使用适合其环境的通用纯文本配置文件。
Config Server通过位于 <code>/{application}/{profile}/{label}/{path}</code> 的附加终结点提供了这些终结点，其中 <code>application</code>, <code>profile</code> 和 <code>label</code> 与常规环境终结点具有相同的含义，但是<code>path</code>是指向以下环境的路径 文件名（例如<code>log.xml</code>）。
该端点的源文件与环境端点的定位方式相同。
属性和YAML文件使用相同的搜索路径。
但是，不是汇总所有匹配资源，而是仅返回要匹配的第一个资源。</p>
</div>
<div class="paragraph">
<p>定位资源后，将有效的<code>环境</code>用于提供的应用程序名称，配置文件和标签，以解析常规格式（<code>${&#8230;&#8203;}</code>）的占位符。
这样，资源端点与环境端点紧密集成在一起。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
与用于环境配置的源文件一样，<code>profile</code> 用于解析文件名。
因此，如果要使用特定于配置文件的文件，则可以通过名为<code>logback-development.xml</code>的文件（优先于<code>logback.xml</code>）来解析 <code>/*/development/*/logback.xml</code> 。
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
如果不想提供<code>label</code>，而是让服务器使用默认标签，则可以提供<code>useDefaultLabel</code>请求参数。
因此，<code>默认</code>配置文件的上述示例可能是 <code>/sample/default/nginx.conf?useDefaultLabel</code>。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>目前，Spring Cloud Config可以为git，SVN，本机后端和AWS S3提供纯文本。
对git，SVN和本机后端的支持是相同的。 AWS S3的工作方式略有不同。
以下部分显示了每个部分的工作方式：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#spring-cloud-config-serving-plain-text-git-svn-native-backends">Git、SVN 和本地后端</a></p>
</li>
<li>
<p><a href="#spring-cloud-config-serving-plain-text-aws-s3">AWS S3</a></p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="spring-cloud-config-serving-plain-text-git-svn-native-backends">Git、SVN 和本地后端</h3>
<div class="paragraph">
<p>考虑以下用于GIT或SVN仓库或本机后端的示例：</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>application.yml
nginx.conf</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p><code>nginx.conf</code>可能类似于以下清单：</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>server {
    listen              80;
    server_name         ${nginx.server.name};
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p><code>application.yml</code>可能类似于以下清单：</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">nginx:
  server:
    name: example.com
---
spring:
  profiles: development
nginx:
  server:
    name: develop.com</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p><code>/sample/default/master/nginx.conf</code> 资源可能如下所示：</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>server {
    listen              80;
    server_name         example.com;
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p><code>/sample/development/master/nginx.conf</code> 如下所示:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>server {
    listen              80;
    server_name         develop.com;
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="spring-cloud-config-serving-plain-text-aws-s3">AWS S3</h3>
<div class="paragraph">
<p>To enable serving plain text for AWS s3, the Config Server application needs to include a dependency on Spring Cloud AWS.
For details on how to set up that dependency, see the
<a href="https://cloud.spring.io/spring-cloud-static/spring-cloud-aws/2.1.3.RELEASE/single/spring-cloud-aws.html#_spring_cloud_aws_maven_dependency_management">Spring Cloud AWS Reference Guide</a>.
Then you need to configure Spring Cloud AWS, as described in the
<a href="https://cloud.spring.io/spring-cloud-static/spring-cloud-aws/2.1.3.RELEASE/single/spring-cloud-aws.html#_configuring_credentials">Spring Cloud AWS Reference Guide</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_解密纯文本">解密纯文本</h3>
<div class="paragraph">
<p>默认情况下，纯文本文件中的加密值不会被解密。 为了对纯文本文件启用解密，请在 <code>bootstrap.[yml|properties]</code> 中设置 <code>spring.cloud.config.server.encrypt.enabled=true</code> 和 <code>spring.cloud.config.server.encrypt.plainTextEncrypt=true</code></p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
仅YAML，JSON和properties 支持解密纯文本文件。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>如果启用了此功能，并且请求了不受支持的文件扩展名，则文件中的任何加密值都不会被解密。</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_嵌入式配置服务器">嵌入式配置服务器</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Config 服务端最好作为独立应用程序运行。
但是，如果需要，可以将其嵌入另一个应用程序。
为此，请使用<code>@EnableConfigServer</code>批注。
在这种情况下，名为<code>spring.cloud.config.server.bootstrap</code>的可选属性可能很有用。
它是一个标志，指示服务器是否应从其自己的远程仓库中进行配置。
默认情况下，该标志为关闭状态，因为它会延迟启动。
但是，当嵌入到另一个应用程序中时，以与其他任何应用程序相同的方式进行初始化是有意义的。
将<code>spring.cloud.config.server.bootstrap</code>设置为<code>true</code>时，还必须使用<a href="#composite-environment-repositories">复杂多环境仓库</a>。
例如</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  application:
    name: configserver
  profiles:
    active: composite
  cloud:
    config:
      server:
        composite:
          - type: native
            search-locations: ${HOME}/Desktop/config
        bootstrap: true</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
如果使用bootstrap标志，则配置服务器需要在<code>bootstrap.yml</code>中配置其名称和仓库URI。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>要更改服务器端点的位置，可以（可选）设置 <code>spring.cloud.config.server.prefix</code>（例如，<code>/config</code>），以在前缀下提供资源。
前缀应以 <code>/</code> 开头，但不能以 <code>/</code> 结尾。
它应用于Config Server中的<code>@RequestMappings</code>（即，在Spring Boot <code>server.servletPath</code>和<code>server.contextPath</code>前缀之下）。</p>
</div>
<div class="paragraph">
<p>如果要直接从后端仓库（而不是从配置服务器）读取应用程序的配置，则基本上需要没有端点的嵌入式配置服务器。
您可以不使用<code>@EnableConfigServer</code>注解（设置 <code>spring.cloud.config.server.bootstrap=true</code>）来完全关闭端点。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_推送通知和_spring_cloud_bus">推送通知和 Spring Cloud Bus</h2>
<div class="sectionbody">
<div class="paragraph">
<p>许多源代码仓库提供程序（例如Github，Gitlab，Gitea，Gitee，Gogs或Bitbucket）都通过Webhook通知您仓库中的更改。
您可以通过提供商的用户界面将Webhook配置为URL和感兴趣的一组事件。
例如， <a href="https://developer.github.com/v3/activity/events/types/#pushevent">Github</a> 使用POST方法的Webhook，其JSON主体包含提交列表和设置为 <code>push</code> 的 header（<code>X-Github-Event</code>）。
如果您添加了依赖库 <code>spring-cloud-config-monitor</code> 并在Config Server中激活Spring Cloud Bus，那么将启用<code>/monitor</code>端点。</p>
</div>
<div class="paragraph">
<p>激活Webhook后，配置服务器将发送一个<code>RefreshRemoteApplicationEvent</code>，该事件针对它认为可能已更改的应用程序。
变化检测可以被策略化。
但是，默认情况下，它会查找与应用程序名称匹配的文件中的更改（例如，<code>foo.properties</code>针对<code>foo</code>应用程序，而<code>application.properties</code>针对所有应用程序）。
当您想覆盖该行为时，可以使用的策略是<code>PropertyPathNotificationExtractor</code>，它接受请求header和body作为参数，并返回已更改文件路径的列表。</p>
</div>
<div class="paragraph">
<p>默认配置可与Github，Gitlab，Gitea，Gitee，Gogs或Bitbucket一起使用。
除了来自Github，Gitlab，Gitee或Bitbucket的JSON通知之外，您还可以通过以 <code>path={application}</code> 模式使用具有形式编码的主体参数的POST到 <code>/monitor</code> 来触发更改通知。
这样做会向与 <code>{application}</code> 模式匹配的应用程序广播（可以包含通配符）。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
仅当在配置服务器和客户端应用程序中都激活了<code>spring-cloud-bus</code>时，才会发送<code>RefreshRemoteApplicationEvent</code>。
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
默认配置还检测本地git仓库中的文件系统更改。 在这种情况下，不使用Webhook。 但是，一旦您编辑了配置文件，就会广播刷新。
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_spring_cloud_config_客户端">Spring Cloud Config 客户端</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Spring Boot应用程序可以立即使用Spring Config 服务器端（或应用程序开发人员提供的其他外部属性源）。
它还选择了一些与<code>Environment</code>更改事件相关的其他有用功能。</p>
</div>
<div class="sect2">
<h3 id="config-first-bootstrap">配置第一个 Bootstrap</h3>
<div class="paragraph">
<p>在类路径上具有Spring Cloud Config Client的任何应用程序的默认行为如下：
当配置客户端启动时，它将绑定到Config Server（通过<code>spring.cloud.config.uri</code>引导程序配置属性）并初始化Spring <code>Environment</code> 与远程资源来源。</p>
</div>
<div class="paragraph">
<p>此行为的最终结果是，所有要使用Config Server的客户端应用程序都需要一个<code>bootstrap.yml</code>（或环境变量），其服务器地址在<code>spring.cloud.config.uri</code>中设置（默认为 "http://localhost:8888" ）。</p>
</div>
</div>
<div class="sect2">
<h3 id="discovery-first-bootstrap">发现第一个 Bootstrap</h3>
<div class="paragraph">
<p>如果您使用诸如Spring Cloud Netflix和Eureka Service Discovery或Spring Cloud Consul之类的<code>DiscoveryClient</code>实施，则可以让Config Server向Discovery Service注册。
但是，在默认的 <code>"Config First"</code>(配置优先) 模式下，客户端无法注册。</p>
</div>
<div class="paragraph">
<p>如果您更喜欢使用<code>DiscoveryClient</code>查找配置服务器，则可以通过设置 <code>spring.cloud.config.discovery.enabled=true</code>（默认值为<code>false</code>）来进行。
这样做的最终结果是，所有客户端应用程序都需要带有适当发现配置的<code>bootstrap.yml</code>（或环境变量）。
例如，对于Spring Cloud Netflix，您需要定义Eureka服务器地址（例如，在 <code>eureka.client.serviceUrl.defaultZone</code> 中）。
使用此选项的代价是启动时需要进行额外的网络往返，以查找服务注册。
好处是，只要发现服务是固定点，配置服务器就可以更改其坐标。
默认服务ID是<code>configserver</code>，但是您可以通过设置 <code>spring.cloud.config.discovery.serviceId</code> 在客户端上进行更改（以及在服务器上，以一种通常的服务方式，例如通过设置 <code>spring.application.name</code> 来更改）。</p>
</div>
<div class="paragraph">
<p>发现客户端实现均支持某种元数据映射（例如，对于Eureka，我们有<code>eureka.instance.metadataMap</code>）。
Config Server的某些其他属性可能需要在其服务注册元数据中进行配置，以便客户端能够正确连接。
如果Config Server受HTTP Basic保护，则可以将凭据配置为<code>user</code>和<code>password</code>。
另外，如果Config Server具有上下文路径，则可以设置<code>configPath</code>。
例如，以下YAML文件适用于作为Eureka客户端的Config Server：</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">eureka:
  instance:
    ...
    metadataMap:
      user: osufhalskjrtl
      password: lviuhlszvaorhvlo5847
      configPath: /config</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="config-client-fail-fast">Config 客户端的快速失败</h3>
<div class="paragraph">
<p>在某些情况下，如果服务无法连接到Config Server，您可能希望启动立即失败。
如果这是您所需的行为，请通过配置引导程序属性 <code>spring.cloud.config.fail-fast=true</code> 以使客户端遇到异常就立刻暂停。</p>
</div>
</div>
<div class="sect2">
<h3 id="config-client-retry">Config 客户端的重试</h3>
<div class="paragraph">
<p>如果您希望配置服务器在应用程序启动时偶尔不可用，则可以使其在失败后继续尝试。
首先，您需要设置 <code>spring.cloud.config.fail-fast=true</code>。
然后，您需要将<code>spring-retry</code>和<code>spring-boot-starter-aop</code>添加到您的类路径中。
默认行为是重试六次，初始回退间隔为1000ms，随后的回退的指数乘数为1.1。
您可以通过设置 <code>spring.cloud.config.retry.*</code> 配置属性来配置这些属性（以及其他属性）。</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
要完全控制重试行为，请添加ID为<code>configServerRetryInterceptor</code>的<code>RetryOperationsInterceptor</code>类型的<code>@Bean</code>。
Spring Retry有一个<code>RetryInterceptorBuilder</code>，它支持创建一个。
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_查找远程配置资源">查找远程配置资源</h3>
<div class="paragraph">
<p>Config Service提供来自 <code>/{application}/{profile}/{label}</code> 的属性源，其中客户端应用程序中的默认绑定如下：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>"name" = <code>${spring.application.name}</code></p>
</li>
<li>
<p>"profile" = <code>${spring.profiles.active}</code> (其实是 <code>Environment.getActiveProfiles()</code>)</p>
</li>
<li>
<p>"label" = "master"</p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
设置属性 <code>${spring.application.name}</code> 时，请不要在应用名称前加上保留字<code>application-</code>以防止解析正确的属性源时出现问题。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>您可以通过设置 <code>spring.cloud.config.*</code> （其中<code>*</code>是<code>name</code>，<code>profile</code>或<code>label</code>）来覆盖所有这些内容。
该<code>标签</code>对于回滚到以前的配置版本很有用。
使用默认的Config Server实现，它可以是git标签，分支名称或提交ID。
标签也可以逗号分隔的列表形式提供。
在这种情况下，列表中的项目将一一尝试直到成功为止。
在要素分支上工作时，此行为可能很有用。
例如，您可能想使配置标签与分支对齐，但使其成为可选（在这种情况下，请使用 <code>spring.cloud.config.label=myfeature,develop</code> ）。</p>
</div>
</div>
<div class="sect2">
<h3 id="_为配置服务器指定多个地址">为配置服务器指定多个地址</h3>
<div class="paragraph">
<p>为了确保在部署了Config Server的多个实例并且不时会出现一个或多个实例不可用的情况下确保高可用性，可以指定多个URL（作为 <code>spring.cloud.config.uri</code> 属性下的逗号分隔列表），或让您的所有实例在Eureka之类的服务注册表中注册（如果使用Discovery-First Bootstrap模式）。
请注意，只有在未运行Config Server时（即，应用程序退出时）或发生连接超时时，这样做才能确保高可用性。
例如，如果Config Server返回500（内部服务器错误）响应，或者Config Client从Config Server收到401（由于凭据错误或其他原因），则Config Client不会尝试从其他URL获取属性。
此类错误表示用户问题，而不是可用性问题。</p>
</div>
<div class="paragraph">
<p>如果您在Config Server上使用HTTP基本安全性，则当前只有在将 <code>spring.cloud.config.uri</code> 属性下指定的每个URL中嵌入凭据时，才可能支持per-Config Server身份验证凭据。
如果使用任何其他类型的安全性机制，则您（当前）不能支持每个Config Server的身份验证和授权。</p>
</div>
</div>
<div class="sect2">
<h3 id="_配置超时">配置超时</h3>
<div class="paragraph">
<p>如果要配置超时阈值：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>可以使用属性 <code>spring.cloud.config.request-read-timeout</code> 配置读取超时。</p>
</li>
<li>
<p>可以使用属性 <code>spring.cloud.config.request-connect-timeout</code> 来配置连接超时。</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_安全_2">安全</h3>
<div class="paragraph">
<p>如果在服务器上使用基本HTTP安全验证，则客户端需要知道密码（如果不是默认用户名，那么还需要知道用户名）。
您可以通过配置服务器URI或通过单独的 username 和 password 属性来指定用户名和密码，如以下示例所示：</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
     uri: https://user:secret@myconfig.mycompany.com</code></pre>
</div>
</div>
<div class="paragraph">
<p>以下示例显示了传递相同信息的另一种方法：</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
     uri: https://myconfig.mycompany.com
     username: user
     password: secret</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>spring.cloud.config.password</code> 和 <code>spring.cloud.config.username</code> 值会覆盖URI中提供的任何内容。</p>
</div>
<div class="paragraph">
<p>如果您在Cloud Foundry上部署应用程序，则提供密码的最佳方法是通过服务凭据（例如URI，因为它不需要在配置文件中）。
以下示例在本地运行，并且适用于Cloud Foundry上名为<code>configserver</code>的用户提供的服务：</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
     uri: ${vcap.services.configserver.credentials.uri:http://user:password@localhost:8888}</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果使用其他形式的安全性，则可能需要向 <code>ConfigServicePropertySourceLocator</code> <a href="#custom-rest-template">提供自定义的 RestTemplate</a>（例如，通过在引导上下文中进行抓取并将其注入）。</p>
</div>
<div class="sect3">
<h4 id="_健康指标_2">健康指标</h4>
<div class="paragraph">
<p>Config Client提供一个Spring Boot Health Indicator，该指示器尝试从Config Server加载配置。
可以通过设置 <code>health.config.enabled=false</code> 来禁用运行状况指示器。
由于性能原因，响应会被缓存。
默认的生存时间为5分钟。
要更改该值，请设置 <code>health.config.time-to-live</code> 属性（以毫秒为单位）。</p>
</div>
</div>
<div class="sect3">
<h4 id="custom-rest-template">提供自定义的 RestTemplate</h4>
<div class="paragraph">
<p>在某些情况下，您可能需要自定义来自客户端对配置服务器的请求。
通常，这样做涉及传递特殊的<code>Authorization</code>标头以验证对服务器的请求。
提供自定义的<code>RestTemplate</code>：</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>使用<code>PropertySourceLocator</code>的实现创建一个新的配置Bean，如以下示例所示：</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="title">CustomConfigServiceBootstrapConfiguration.java</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">@Configuration
public class CustomConfigServiceBootstrapConfiguration {
    @Bean
    public ConfigServicePropertySourceLocator configServicePropertySourceLocator() {
        ConfigClientProperties clientProperties = configClientProperties();
       ConfigServicePropertySourceLocator configServicePropertySourceLocator =  new ConfigServicePropertySourceLocator(clientProperties);
        configServicePropertySourceLocator.setRestTemplate(customRestTemplate(clientProperties));
        return configServicePropertySourceLocator;
    }
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
为了简化添加 <code>Authorization</code> header 的方法，可以改用 <code>spring.cloud.config.headers.*</code> 属性。
</td>
</tr>
</table>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>在 <code>resources/META-INF</code> 中，创建一个名为 <code>spring.factories</code> 的文件并指定您的自定义配置，如以下示例所示：</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="title">spring.factories</div>
<div class="content">
<pre class="highlight"><code class="language-properties" data-lang="properties">org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_vault">Vault</h4>
<div class="paragraph">
<p>When using Vault as a backend to your config server, the client needs to supply a token for the server to retrieve values from Vault.
This token can be provided within the client by setting <code>spring.cloud.config.token</code>
in <code>bootstrap.yml</code>, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="title">bootstrap.yml</div>
<div class="content">
<pre class="highlight"><code class="language-yaml" data-lang="yaml">spring:
  cloud:
    config:
      token: YourVaultToken</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_vault_中的嵌套密钥">Vault 中的嵌套密钥</h3>
<div class="paragraph">
<p>Vault supports the ability to nest keys in a value stored in Vault, as shown in the following example:</p>
</div>
<div class="paragraph">
<p><code>echo -n '{"appA": {"secret": "appAsecret"}, "bar": "baz"}' | vault write secret/myapp -</code></p>
</div>
<div class="paragraph">
<p>This command writes a JSON object to your Vault.
To access these values in Spring, you would use the traditional dot(<code>.</code>) annotation, as shown in the following example</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">@Value("${appA.secret}")
String name = "World";</code></pre>
</div>
</div>
<div class="paragraph">
<p>The preceding code would sets the value of the <code>name</code> variable to <code>appAsecret</code>.</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>